Skip to content

Rollup of 6 pull requests #96426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 42 additions & 77 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
//! Error reporting machinery for lifetime errors.

use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_infer::infer::{
error_reporting::nice_region_error::NiceRegionError,
error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
RelateParamBound,
error_reporting::nice_region_error::{self, find_param_with_region, NiceRegionError},
error_reporting::unexpected_hidden_region_diagnostic,
NllRegionVariableOrigin, RelateParamBound,
};
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::symbol::{kw, sym};
use rustc_span::{BytePos, Span};
use rustc_span::symbol::sym;
use rustc_span::Span;

use crate::borrowck_errors;

Expand Down Expand Up @@ -651,82 +651,47 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fr_name: RegionName,
outlived_fr: RegionVid,
) {
if let (Some(f), Some(ty::ReStatic)) =
(self.to_error_region(fr), self.to_error_region(outlived_fr).as_deref())
if let (Some(f), Some(outlived_f)) =
(self.to_error_region(fr), self.to_error_region(outlived_fr))
{
if let Some(&ty::Opaque(did, substs)) = self
if *outlived_f != ty::ReStatic {
return;
}

let fn_returns = self
.infcx
.tcx
.is_suitable_region(f)
.map(|r| r.def_id)
.and_then(|id| self.infcx.tcx.return_type_impl_trait(id))
.map(|(ty, _)| ty.kind())
{
// Check whether or not the impl trait return type is intended to capture
// data with the static lifetime.
//
// eg. check for `impl Trait + 'static` instead of `impl Trait`.
let has_static_predicate = {
let bounds = self.infcx.tcx.explicit_item_bounds(did);

let mut found = false;
for (bound, _) in bounds {
if let ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_, r)) =
bound.kind().skip_binder()
{
let r = r.subst(self.infcx.tcx, substs);
if r.is_static() {
found = true;
break;
} else {
// If there's already a lifetime bound, don't
// suggest anything.
return;
}
}
}

found
};
.map(|r| self.infcx.tcx.return_type_impl_or_dyn_traits(r.def_id))
.unwrap_or_default();

debug!(
"add_static_impl_trait_suggestion: has_static_predicate={:?}",
has_static_predicate
);
let static_str = kw::StaticLifetime;
// If there is a static predicate, then the only sensible suggestion is to replace
// fr with `'static`.
if has_static_predicate {
diag.help(&format!("consider replacing `{fr_name}` with `{static_str}`"));
} else {
// Otherwise, we should suggest adding a constraint on the return type.
let span = self.infcx.tcx.def_span(did);
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
let suggestable_fr_name = if fr_name.was_named() {
fr_name.to_string()
} else {
"'_".to_string()
};
let span = if snippet.ends_with(';') {
// `type X = impl Trait;`
span.with_hi(span.hi() - BytePos(1))
} else {
span
};
let suggestion = format!(" + {suggestable_fr_name}");
let span = span.shrink_to_hi();
diag.span_suggestion(
span,
&format!(
"to allow this `impl Trait` to capture borrowed data with lifetime \
`{fr_name}`, add `{suggestable_fr_name}` as a bound",
),
suggestion,
Applicability::MachineApplicable,
);
}
}
if fn_returns.is_empty() {
return;
}

let param = if let Some(param) = find_param_with_region(self.infcx.tcx, f, outlived_f) {
param
} else {
return;
};

let lifetime = if f.has_name() { fr_name.to_string() } else { "'_".to_string() };

let arg = match param.param.pat.simple_ident() {
Some(simple_ident) => format!("argument `{}`", simple_ident),
None => "the argument".to_string(),
};
let captures = format!("captures data from {}", arg);

return nice_region_error::suggest_new_region_bound(
self.infcx.tcx,
diag,
fn_returns,
lifetime,
Some(arg),
captures,
Some((param.param_ty_span, param.param_ty.to_string())),
);
}
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
span: Span,
) -> Result<&'ll Value, ()> {
// macros for error handling:
#[cfg_attr(not(bootstrap), allow(unused_macro_rules))]
macro_rules! emit_error {
($msg: tt) => {
emit_error!($msg, )
Expand Down Expand Up @@ -1144,6 +1145,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
span: Span,
args: &[OperandRef<'tcx, &'ll Value>],
) -> Result<&'ll Value, ()> {
#[cfg_attr(not(bootstrap), allow(unused_macro_rules))]
macro_rules! emit_error {
($msg: tt) => {
emit_error!($msg, )
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,9 @@ pub struct SyntaxExtension {
/// Built-in macros have a couple of special properties like availability
/// in `#[no_implicit_prelude]` modules, so we have to keep this flag.
pub builtin_name: Option<Symbol>,
/// Rule spans. Used for linting. If the macro is not made up of rules,
/// it's empty.
pub rule_spans: Vec<Span>,
}

impl SyntaxExtension {
Expand Down Expand Up @@ -740,6 +743,7 @@ impl SyntaxExtension {
edition,
builtin_name: None,
kind,
rule_spans: Vec::new(),
}
}

Expand All @@ -753,6 +757,7 @@ impl SyntaxExtension {
edition: Edition,
name: Symbol,
attrs: &[ast::Attribute],
rule_spans: Vec<Span>,
) -> SyntaxExtension {
let allow_internal_unstable =
attr::allow_internal_unstable(sess, &attrs).collect::<Vec<Symbol>>();
Expand Down Expand Up @@ -800,6 +805,7 @@ impl SyntaxExtension {
helper_attrs,
edition,
builtin_name,
rule_spans,
}
}

Expand Down Expand Up @@ -887,6 +893,8 @@ pub trait ResolverExpand {
force: bool,
) -> Result<Lrc<SyntaxExtension>, Indeterminate>;

fn record_macro_rule_usage(&mut self, mac_id: NodeId, rule_index: usize);

fn check_unused_macros(&mut self);

// Resolver interfaces for specific built-in macros.
Expand Down
46 changes: 31 additions & 15 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ impl<'a> ParserAnyMacro<'a> {
}

struct MacroRulesMacroExpander {
id: NodeId,
name: Ident,
span: Span,
transparency: Transparency,
Expand All @@ -179,6 +180,7 @@ impl TTMacroExpander for MacroRulesMacroExpander {
cx,
sp,
self.span,
self.id,
self.name,
self.transparency,
input,
Expand Down Expand Up @@ -207,6 +209,7 @@ fn generic_extension<'cx, 'tt>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
def_span: Span,
id: NodeId,
name: Ident,
transparency: Transparency,
arg: TokenStream,
Expand Down Expand Up @@ -297,6 +300,8 @@ fn generic_extension<'cx, 'tt>(
let mut p = Parser::new(sess, tts, false, None);
p.last_type_ascription = cx.current_expansion.prior_type_ascription;

cx.resolver.record_macro_rule_usage(id, i);

// Let the context choose how to interpret the result.
// Weird, but useful for X-macros.
return Box::new(ParserAnyMacro {
Expand Down Expand Up @@ -375,7 +380,7 @@ pub fn compile_declarative_macro(
edition: Edition,
) -> SyntaxExtension {
debug!("compile_declarative_macro: {:?}", def);
let mk_syn_ext = |expander| {
let mk_syn_ext = |expander, rule_spans| {
SyntaxExtension::new(
sess,
SyntaxExtensionKind::LegacyBang(expander),
Expand All @@ -384,8 +389,10 @@ pub fn compile_declarative_macro(
edition,
def.ident.name,
&def.attrs,
rule_spans,
)
};
let dummy_syn_ext = || mk_syn_ext(Box::new(macro_rules_dummy_expander), Vec::new());

let diag = &sess.parse_sess.span_diagnostic;
let lhs_nm = Ident::new(sym::lhs, def.span);
Expand Down Expand Up @@ -446,17 +453,17 @@ pub fn compile_declarative_macro(
let s = parse_failure_msg(&token);
let sp = token.span.substitute_dummy(def.span);
sess.parse_sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit();
return mk_syn_ext(Box::new(macro_rules_dummy_expander));
return dummy_syn_ext();
}
Error(sp, msg) => {
sess.parse_sess
.span_diagnostic
.struct_span_err(sp.substitute_dummy(def.span), &msg)
.emit();
return mk_syn_ext(Box::new(macro_rules_dummy_expander));
return dummy_syn_ext();
}
ErrorReported => {
return mk_syn_ext(Box::new(macro_rules_dummy_expander));
return dummy_syn_ext();
}
};

Expand Down Expand Up @@ -531,6 +538,11 @@ pub fn compile_declarative_macro(
None => {}
}

// Compute the spans of the macro rules
// We only take the span of the lhs here,
// so that the spans of created warnings are smaller.
let rule_spans = lhses.iter().map(|lhs| lhs.span()).collect::<Vec<_>>();

// Convert the lhses into `MatcherLoc` form, which is better for doing the
// actual matching. Unless the matcher is invalid.
let lhses = if valid {
Expand All @@ -550,17 +562,21 @@ pub fn compile_declarative_macro(
vec![]
};

mk_syn_ext(Box::new(MacroRulesMacroExpander {
name: def.ident,
span: def.span,
transparency,
lhses,
rhses,
valid,
// Macros defined in the current crate have a real node id,
// whereas macros from an external crate have a dummy id.
is_local: def.id != DUMMY_NODE_ID,
}))
mk_syn_ext(
Box::new(MacroRulesMacroExpander {
name: def.ident,
span: def.span,
id: def.id,
transparency,
lhses,
rhses,
valid,
// Macros defined in the current crate have a real node id,
// whereas macros from an external crate have a dummy id.
is_local: def.id != DUMMY_NODE_ID,
}),
rule_spans,
)
}

fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod trait_impl_difference;
mod util;

pub use static_impl_trait::suggest_new_region_bound;
pub use util::find_param_with_region;

impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
Expand Down
Loading