Skip to content

Commit

Permalink
Auto merge of #104437 - matthiaskrgr:rollup-n5jdg9v, r=matthiaskrgr
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Nov 15, 2022
2 parents 357f660 + 55ff8bf commit 6d651a2
Show file tree
Hide file tree
Showing 51 changed files with 724 additions and 206 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {

walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
});
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
}
ItemKind::Impl(box Impl {
Expand Down Expand Up @@ -1168,7 +1169,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
walk_list!(self, visit_attribute, &item.attrs);
return;
return; // Avoid visiting again
}
ItemKind::Mod(unsafety, ref mod_kind) => {
if let Unsafe::Yes(span) = unsafety {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0322.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
The `Sized` trait was implemented explicitly.
A built-in trait was implemented explicitly. All implementations of the trait
are provided automatically by the compiler.

Erroneous code example:

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/parser.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,6 @@ parser_fn_ptr_with_generics = function pointer types may not have generic parame
[true] the
*[false] a
} `for` parameter list
parser_invalid_identifier_with_leading_number = expected identifier, found number literal
.label = identifiers cannot start with a number
48 changes: 47 additions & 1 deletion compiler/rustc_expand/src/mbe/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub(crate) use ParseResult::*;
use crate::mbe::{macro_rules::Tracker, KleeneOp, TokenTree};

use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorGuaranteed;
Expand All @@ -86,6 +87,7 @@ use rustc_span::symbol::MacroRulesNormalizedIdent;
use rustc_span::Span;
use std::borrow::Cow;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fmt::Display;

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

impl MatcherLoc {
pub(super) fn span(&self) -> Option<Span> {
match self {
MatcherLoc::Token { token } => Some(token.span),
MatcherLoc::Delimited => None,
MatcherLoc::Sequence { .. } => None,
MatcherLoc::SequenceKleeneOpNoSep { .. } => None,
MatcherLoc::SequenceSep { .. } => None,
MatcherLoc::SequenceKleeneOpAfterSep { .. } => None,
MatcherLoc::MetaVarDecl { span, .. } => Some(*span),
MatcherLoc::Eof => None,
}
}
}

impl Display for MatcherLoc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => {
write!(f, "`{}`", pprust::token_to_string(token))
}
MatcherLoc::MetaVarDecl { bind, kind, .. } => {
write!(f, "meta-variable `${bind}")?;
if let Some(kind) = kind {
write!(f, ":{}", kind)?;
}
write!(f, "`")?;
Ok(())
}
MatcherLoc::Eof => f.write_str("end of macro"),

// These are not printed in the diagnostic
MatcherLoc::Delimited => f.write_str("delimiter"),
MatcherLoc::Sequence { .. } => f.write_str("sequence start"),
MatcherLoc::SequenceKleeneOpNoSep { .. } => f.write_str("sequence end"),
MatcherLoc::SequenceKleeneOpAfterSep { .. } => f.write_str("sequence end"),
}
}
}

pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
fn inner(
tts: &[TokenTree],
Expand Down Expand Up @@ -398,6 +440,10 @@ impl TtParser {
}
}

pub(super) fn has_no_remaining_items_for_step(&self) -> bool {
self.cur_mps.is_empty()
}

/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
/// produce more mps in `next_mps` and `bb_mps`.
///
Expand Down
39 changes: 29 additions & 10 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ fn expand_macro<'cx>(
return result;
}

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

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

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

if let Some(span) = remaining_matcher.span() {
err.span_note(span, format!("while trying to match {remaining_matcher}"));
} else {
err.note(format!("while trying to match {remaining_matcher}"));
}

// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
if let Some((arg, comma_span)) = arg.add_comma() {
for lhs in lhses {
Expand Down Expand Up @@ -379,17 +385,22 @@ fn expand_macro<'cx>(
}

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

impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx> {
fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {
// Empty for now.
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) {
if self.remaining_matcher.is_none()
|| (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof)
{
self.remaining_matcher = Some(matcher);
}
}

fn after_arm(&mut self, result: &NamedParseResult) {
Expand All @@ -398,8 +409,16 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx>
unreachable!("should not collect detailed info for successful macro match");
}
Failure(token, msg) => match self.best_failure {
Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {}
_ => self.best_failure = Some((token.clone(), msg)),
Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {}
_ => {
self.best_failure = Some((
token.clone(),
msg,
self.remaining_matcher
.expect("must have collected matcher already")
.clone(),
))
}
},
Error(err_sp, msg) => {
let span = err_sp.substitute_dummy(self.root_span);
Expand All @@ -415,9 +434,9 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx>
}
}

impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx> {
impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self {
Self { cx, best_failure: None, root_span, result: None }
Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None }
}
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
),
rustc_attr!(
rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: false,
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
),
rustc_attr!(
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
Expand Down
66 changes: 16 additions & 50 deletions compiler/rustc_hir_analysis/src/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.

use rustc_errors::struct_span_err;
use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::sym;
use rustc_trait_selection::traits;

mod builtin;
Expand Down Expand Up @@ -39,61 +40,26 @@ fn enforce_trait_manually_implementable(
impl_def_id: LocalDefId,
trait_def_id: DefId,
) {
let did = Some(trait_def_id);
let li = tcx.lang_items();
let impl_header_span = tcx.def_span(impl_def_id);

// Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
if did == li.pointee_trait() {
struct_span_err!(
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
let trait_name = tcx.item_name(trait_def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
"explicit impls for the `Pointee` trait are not permitted"
)
.span_label(impl_header_span, "impl of `Pointee` not allowed")
.emit();
return;
}

if did == li.discriminant_kind_trait() {
struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
"explicit impls for the `DiscriminantKind` trait are not permitted"
)
.span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
.emit();
return;
}

if did == li.sized_trait() {
struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
"explicit impls for the `Sized` trait are not permitted"
)
.span_label(impl_header_span, "impl of `Sized` not allowed")
.emit();
return;
}

if did == li.unsize_trait() {
struct_span_err!(
tcx.sess,
impl_header_span,
E0328,
"explicit impls for the `Unsize` trait are not permitted"
)
.span_label(impl_header_span, "impl of `Unsize` not allowed")
.emit();
return;
}
"explicit impls for the `{trait_name}` trait are not permitted"
);
err.span_label(impl_header_span, format!("impl of `{trait_name}` not allowed"));

// Maintain explicit error code for `Unsize`, since it has a useful
// explanation about using `CoerceUnsized` instead.
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
err.code(error_code!(E0328));
}

if tcx.features().unboxed_closures {
// the feature gate allows all Fn traits
err.emit();
return;
}

Expand Down
43 changes: 10 additions & 33 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,34 +173,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'tcx>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
ty::Opaque(def_id, substs) => {
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
let sig =
bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
.kind()
.skip_binder()
{
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
Some(span),
pred.kind().rebind(proj_predicate),
),
_ => None,
});

let kind = bounds
.0
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(tp) => {
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
}
_ => None,
})
.fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
trace!(?sig, ?kind);
(sig, kind)
}
ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
),
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
Expand All @@ -211,7 +186,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did));
(sig, kind)
}
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
),
ty::FnPtr(sig) => {
let expected_sig = ExpectedSig { cause_span: None, sig };
(Some(expected_sig), Some(ty::ClosureKind::Fn))
Expand All @@ -220,19 +197,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn deduce_expectations_from_obligations(
fn deduce_signature_from_predicates(
&self,
expected_vid: ty::TyVid,
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
let mut expected_sig = None;
let mut expected_kind = None;

for obligation in traits::elaborate_obligations(
for obligation in traits::elaborate_predicates_with_span(
self.tcx,
// Reverse the obligations here, since `elaborate_*` uses a stack,
// and we want to keep inference generally in the same order of
// the registered obligations.
self.obligations_for_self_ty(expected_vid).rev().collect(),
predicates.rev(),
) {
debug!(?obligation.predicate);
let bound_predicate = obligation.predicate.kind();
Expand Down
Loading

0 comments on commit 6d651a2

Please sign in to comment.