Skip to content

Commit 6d651a2

Browse files
committed
Auto merge of #104437 - matthiaskrgr:rollup-n5jdg9v, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #103439 (Show note where the macro failed to match) - #103734 (Adjust stabilization version to 1.65.0 for wasi fds) - #104148 (Visit attributes of trait impl items during AST validation) - #104241 (Move most of unwind's build script to lib.rs) - #104258 (Deduce closure signature from a type alias `impl Trait`'s supertraits) - #104296 (Walk types more carefully in `ProhibitOpaqueTypes` visitor) - #104309 (Slightly improve error message for invalid identifier) - #104316 (Simplify suggestions for errors in generators.) - #104339 (Add `rustc_deny_explicit_impl`) Failed merges: - #103484 (Add `rust` to `let_underscore_lock` example) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 357f660 + 55ff8bf commit 6d651a2

File tree

51 files changed

+724
-206
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+724
-206
lines changed

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10511051

10521052
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
10531053
});
1054+
walk_list!(self, visit_attribute, &item.attrs);
10541055
return; // Avoid visiting again.
10551056
}
10561057
ItemKind::Impl(box Impl {
@@ -1168,7 +1169,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11681169
});
11691170
walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
11701171
walk_list!(self, visit_attribute, &item.attrs);
1171-
return;
1172+
return; // Avoid visiting again
11721173
}
11731174
ItemKind::Mod(unsafety, ref mod_kind) => {
11741175
if let Unsafe::Yes(span) = unsafety {

Diff for: compiler/rustc_error_codes/src/error_codes/E0322.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
The `Sized` trait was implemented explicitly.
1+
A built-in trait was implemented explicitly. All implementations of the trait
2+
are provided automatically by the compiler.
23

34
Erroneous code example:
45

Diff for: compiler/rustc_error_messages/locales/en-US/parser.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,6 @@ parser_fn_ptr_with_generics = function pointer types may not have generic parame
384384
[true] the
385385
*[false] a
386386
} `for` parameter list
387+
388+
parser_invalid_identifier_with_leading_number = expected identifier, found number literal
389+
.label = identifiers cannot start with a number

Diff for: compiler/rustc_expand/src/mbe/macro_parser.rs

+47-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub(crate) use ParseResult::*;
7676
use crate::mbe::{macro_rules::Tracker, KleeneOp, TokenTree};
7777

7878
use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token};
79+
use rustc_ast_pretty::pprust;
7980
use rustc_data_structures::fx::FxHashMap;
8081
use rustc_data_structures::sync::Lrc;
8182
use rustc_errors::ErrorGuaranteed;
@@ -86,6 +87,7 @@ use rustc_span::symbol::MacroRulesNormalizedIdent;
8687
use rustc_span::Span;
8788
use std::borrow::Cow;
8889
use std::collections::hash_map::Entry::{Occupied, Vacant};
90+
use std::fmt::Display;
8991

9092
/// A unit within a matcher that a `MatcherPos` can refer to. Similar to (and derived from)
9193
/// `mbe::TokenTree`, but designed specifically for fast and easy traversal during matching.
@@ -96,7 +98,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
9698
///
9799
/// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves
98100
/// simply incrementing the current matcher position index by one.
99-
#[derive(Debug)]
101+
#[derive(Debug, PartialEq, Clone)]
100102
pub(crate) enum MatcherLoc {
101103
Token {
102104
token: Token,
@@ -129,6 +131,46 @@ pub(crate) enum MatcherLoc {
129131
Eof,
130132
}
131133

134+
impl MatcherLoc {
135+
pub(super) fn span(&self) -> Option<Span> {
136+
match self {
137+
MatcherLoc::Token { token } => Some(token.span),
138+
MatcherLoc::Delimited => None,
139+
MatcherLoc::Sequence { .. } => None,
140+
MatcherLoc::SequenceKleeneOpNoSep { .. } => None,
141+
MatcherLoc::SequenceSep { .. } => None,
142+
MatcherLoc::SequenceKleeneOpAfterSep { .. } => None,
143+
MatcherLoc::MetaVarDecl { span, .. } => Some(*span),
144+
MatcherLoc::Eof => None,
145+
}
146+
}
147+
}
148+
149+
impl Display for MatcherLoc {
150+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151+
match self {
152+
MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => {
153+
write!(f, "`{}`", pprust::token_to_string(token))
154+
}
155+
MatcherLoc::MetaVarDecl { bind, kind, .. } => {
156+
write!(f, "meta-variable `${bind}")?;
157+
if let Some(kind) = kind {
158+
write!(f, ":{}", kind)?;
159+
}
160+
write!(f, "`")?;
161+
Ok(())
162+
}
163+
MatcherLoc::Eof => f.write_str("end of macro"),
164+
165+
// These are not printed in the diagnostic
166+
MatcherLoc::Delimited => f.write_str("delimiter"),
167+
MatcherLoc::Sequence { .. } => f.write_str("sequence start"),
168+
MatcherLoc::SequenceKleeneOpNoSep { .. } => f.write_str("sequence end"),
169+
MatcherLoc::SequenceKleeneOpAfterSep { .. } => f.write_str("sequence end"),
170+
}
171+
}
172+
}
173+
132174
pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
133175
fn inner(
134176
tts: &[TokenTree],
@@ -398,6 +440,10 @@ impl TtParser {
398440
}
399441
}
400442

443+
pub(super) fn has_no_remaining_items_for_step(&self) -> bool {
444+
self.cur_mps.is_empty()
445+
}
446+
401447
/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
402448
/// produce more mps in `next_mps` and `bb_mps`.
403449
///

Diff for: compiler/rustc_expand/src/mbe/macro_rules.rs

+29-10
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ fn expand_macro<'cx>(
337337
return result;
338338
}
339339

340-
let Some((token, label)) = tracker.best_failure else {
340+
let Some((token, label, remaining_matcher)) = tracker.best_failure else {
341341
return tracker.result.expect("must have encountered Error or ErrorReported");
342342
};
343343

@@ -351,6 +351,12 @@ fn expand_macro<'cx>(
351351

352352
annotate_doc_comment(&mut err, sess.source_map(), span);
353353

354+
if let Some(span) = remaining_matcher.span() {
355+
err.span_note(span, format!("while trying to match {remaining_matcher}"));
356+
} else {
357+
err.note(format!("while trying to match {remaining_matcher}"));
358+
}
359+
354360
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
355361
if let Some((arg, comma_span)) = arg.add_comma() {
356362
for lhs in lhses {
@@ -379,17 +385,22 @@ fn expand_macro<'cx>(
379385
}
380386

381387
/// The tracker used for the slow error path that collects useful info for diagnostics.
382-
struct CollectTrackerAndEmitter<'a, 'cx> {
388+
struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
383389
cx: &'a mut ExtCtxt<'cx>,
390+
remaining_matcher: Option<&'matcher MatcherLoc>,
384391
/// Which arm's failure should we report? (the one furthest along)
385-
best_failure: Option<(Token, &'static str)>,
392+
best_failure: Option<(Token, &'static str, MatcherLoc)>,
386393
root_span: Span,
387394
result: Option<Box<dyn MacResult + 'cx>>,
388395
}
389396

390-
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx> {
391-
fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {
392-
// Empty for now.
397+
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
398+
fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) {
399+
if self.remaining_matcher.is_none()
400+
|| (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof)
401+
{
402+
self.remaining_matcher = Some(matcher);
403+
}
393404
}
394405

395406
fn after_arm(&mut self, result: &NamedParseResult) {
@@ -398,8 +409,16 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx>
398409
unreachable!("should not collect detailed info for successful macro match");
399410
}
400411
Failure(token, msg) => match self.best_failure {
401-
Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {}
402-
_ => self.best_failure = Some((token.clone(), msg)),
412+
Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {}
413+
_ => {
414+
self.best_failure = Some((
415+
token.clone(),
416+
msg,
417+
self.remaining_matcher
418+
.expect("must have collected matcher already")
419+
.clone(),
420+
))
421+
}
403422
},
404423
Error(err_sp, msg) => {
405424
let span = err_sp.substitute_dummy(self.root_span);
@@ -415,9 +434,9 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx>
415434
}
416435
}
417436

418-
impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx> {
437+
impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
419438
fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self {
420-
Self { cx, best_failure: None, root_span, result: None }
439+
Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None }
421440
}
422441
}
423442

Diff for: compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
691691
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
692692
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
693693
),
694+
rustc_attr!(
695+
rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: false,
696+
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
697+
),
694698
rustc_attr!(
695699
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
696700
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \

Diff for: compiler/rustc_hir_analysis/src/coherence/mod.rs

+16-50
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
// done by the orphan and overlap modules. Then we build up various
66
// mappings. That mapping code resides here.
77

8-
use rustc_errors::struct_span_err;
8+
use rustc_errors::{error_code, struct_span_err};
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_middle::ty::query::Providers;
1111
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
12+
use rustc_span::sym;
1213
use rustc_trait_selection::traits;
1314

1415
mod builtin;
@@ -39,61 +40,26 @@ fn enforce_trait_manually_implementable(
3940
impl_def_id: LocalDefId,
4041
trait_def_id: DefId,
4142
) {
42-
let did = Some(trait_def_id);
43-
let li = tcx.lang_items();
4443
let impl_header_span = tcx.def_span(impl_def_id);
4544

46-
// Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
47-
if did == li.pointee_trait() {
48-
struct_span_err!(
45+
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
46+
if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
47+
let trait_name = tcx.item_name(trait_def_id);
48+
let mut err = struct_span_err!(
4949
tcx.sess,
5050
impl_header_span,
5151
E0322,
52-
"explicit impls for the `Pointee` trait are not permitted"
53-
)
54-
.span_label(impl_header_span, "impl of `Pointee` not allowed")
55-
.emit();
56-
return;
57-
}
58-
59-
if did == li.discriminant_kind_trait() {
60-
struct_span_err!(
61-
tcx.sess,
62-
impl_header_span,
63-
E0322,
64-
"explicit impls for the `DiscriminantKind` trait are not permitted"
65-
)
66-
.span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
67-
.emit();
68-
return;
69-
}
70-
71-
if did == li.sized_trait() {
72-
struct_span_err!(
73-
tcx.sess,
74-
impl_header_span,
75-
E0322,
76-
"explicit impls for the `Sized` trait are not permitted"
77-
)
78-
.span_label(impl_header_span, "impl of `Sized` not allowed")
79-
.emit();
80-
return;
81-
}
82-
83-
if did == li.unsize_trait() {
84-
struct_span_err!(
85-
tcx.sess,
86-
impl_header_span,
87-
E0328,
88-
"explicit impls for the `Unsize` trait are not permitted"
89-
)
90-
.span_label(impl_header_span, "impl of `Unsize` not allowed")
91-
.emit();
92-
return;
93-
}
52+
"explicit impls for the `{trait_name}` trait are not permitted"
53+
);
54+
err.span_label(impl_header_span, format!("impl of `{trait_name}` not allowed"));
55+
56+
// Maintain explicit error code for `Unsize`, since it has a useful
57+
// explanation about using `CoerceUnsized` instead.
58+
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
59+
err.code(error_code!(E0328));
60+
}
9461

95-
if tcx.features().unboxed_closures {
96-
// the feature gate allows all Fn traits
62+
err.emit();
9763
return;
9864
}
9965

Diff for: compiler/rustc_hir_typeck/src/closure.rs

+10-33
Original file line numberDiff line numberDiff line change
@@ -173,34 +173,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173173
expected_ty: Ty<'tcx>,
174174
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
175175
match *expected_ty.kind() {
176-
ty::Opaque(def_id, substs) => {
177-
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
178-
let sig =
179-
bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
180-
.kind()
181-
.skip_binder()
182-
{
183-
ty::PredicateKind::Projection(proj_predicate) => self
184-
.deduce_sig_from_projection(
185-
Some(span),
186-
pred.kind().rebind(proj_predicate),
187-
),
188-
_ => None,
189-
});
190-
191-
let kind = bounds
192-
.0
193-
.iter()
194-
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
195-
ty::PredicateKind::Trait(tp) => {
196-
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
197-
}
198-
_ => None,
199-
})
200-
.fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
201-
trace!(?sig, ?kind);
202-
(sig, kind)
203-
}
176+
ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
177+
self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
178+
),
204179
ty::Dynamic(ref object_type, ..) => {
205180
let sig = object_type.projection_bounds().find_map(|pb| {
206181
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@@ -211,7 +186,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
211186
.and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did));
212187
(sig, kind)
213188
}
214-
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
189+
ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
190+
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
191+
),
215192
ty::FnPtr(sig) => {
216193
let expected_sig = ExpectedSig { cause_span: None, sig };
217194
(Some(expected_sig), Some(ty::ClosureKind::Fn))
@@ -220,19 +197,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
220197
}
221198
}
222199

223-
fn deduce_expectations_from_obligations(
200+
fn deduce_signature_from_predicates(
224201
&self,
225-
expected_vid: ty::TyVid,
202+
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
226203
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
227204
let mut expected_sig = None;
228205
let mut expected_kind = None;
229206

230-
for obligation in traits::elaborate_obligations(
207+
for obligation in traits::elaborate_predicates_with_span(
231208
self.tcx,
232209
// Reverse the obligations here, since `elaborate_*` uses a stack,
233210
// and we want to keep inference generally in the same order of
234211
// the registered obligations.
235-
self.obligations_for_self_ty(expected_vid).rev().collect(),
212+
predicates.rev(),
236213
) {
237214
debug!(?obligation.predicate);
238215
let bound_predicate = obligation.predicate.kind();

0 commit comments

Comments
 (0)