Skip to content
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
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1097,14 +1097,14 @@ fn check_region_bounds_on_impl_item<'tcx>(
.expect("expected impl item to have generics or else we can't compare them")
.span;

let mut generics_span = None;
let mut generics_span = tcx.def_span(trait_m.def_id);
let mut bounds_span = vec![];
let mut where_span = None;

if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
&& let Some(trait_generics) = trait_node.generics()
{
generics_span = Some(trait_generics.span);
generics_span = trait_generics.span;
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
// *are* present in the impl.
for p in trait_generics.predicates {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub(crate) struct LifetimesOrBoundsMismatchOnTrait {
#[label]
pub span: Span,
#[label(hir_analysis_generics_label)]
pub generics_span: Option<Span>,
pub generics_span: Span,
#[label(hir_analysis_where_label)]
pub where_span: Option<Span>,
#[label(hir_analysis_bounds_label)]
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_index/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ edition = "2024"
rustc_index_macros = { path = "../rustc_index_macros" }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
smallvec = "1.8.1"
smallvec = { version = "1.8.1", optional = true }
# tidy-alphabetical-end

[features]
Expand All @@ -17,6 +17,7 @@ default = ["nightly"]
nightly = [
"dep:rustc_macros",
"dep:rustc_serialize",
"dep:smallvec",
"rustc_index_macros/nightly",
]
rustc_randomized_layouts = []
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ resolve_added_macro_use =
resolve_ancestor_only =
visibilities can only be restricted to ancestor modules

resolve_anonymous_lifetime_non_gat_report_error =
in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
resolve_anonymous_lifetime_non_gat_report_error = missing lifetime in associated type
.label = this lifetime must come from the implemented type
.note = in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type

resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,8 @@ pub(crate) struct AnonymousLifetimeNonGatReportError {
#[primary_span]
#[label]
pub(crate) lifetime: Span,
#[note]
pub(crate) decl: MultiSpan,
}

#[derive(Subdiagnostic)]
Expand Down
110 changes: 95 additions & 15 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::mem::{replace, swap, take};
use std::ops::ControlFlow;

use rustc_ast::visit::{
AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list,
Expand All @@ -19,21 +20,21 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions,
pluralize,
Applicability, Diag, DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan, StashKey,
Suggestions, pluralize,
};
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::{DelegationFnSig, Visibility};
use rustc_middle::ty::{AssocTag, DelegationFnSig, Visibility};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, SyntaxContext, kw, sym};
use smallvec::{SmallVec, smallvec};
use thin_vec::ThinVec;
use tracing::{debug, instrument, trace};
Expand Down Expand Up @@ -373,11 +374,14 @@ enum LifetimeBinderKind {
FnPtrType,
PolyTrait,
WhereBound,
// Item covers foreign items, ADTs, type aliases, trait associated items and
// trait alias associated items.
Item,
ConstItem,
Function,
Closure,
ImplBlock,
// Covers only `impl` associated types.
ImplAssocType,
}

Expand Down Expand Up @@ -724,6 +728,9 @@ pub(crate) struct DiagMetadata<'ast> {
/// The current impl items (used to suggest).
current_impl_items: Option<&'ast [Box<AssocItem>]>,

/// The current impl items (used to suggest).
current_impl_item: Option<&'ast AssocItem>,

/// When processing impl trait
currently_processing_impl_trait: Option<(TraitRef, Ty)>,

Expand Down Expand Up @@ -1880,9 +1887,31 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
ty: ty.span,
});
} else {
let decl = if !trait_id.is_local()
&& let Some(assoc) = self.diag_metadata.current_impl_item
&& let AssocItemKind::Type(_) = assoc.kind
&& let assocs = self.r.tcx.associated_items(trait_id)
&& let Some(ident) = assoc.kind.ident()
&& let Some(assoc) = assocs.find_by_ident_and_kind(
self.r.tcx,
ident,
AssocTag::Type,
trait_id,
) {
let mut decl: MultiSpan =
self.r.tcx.def_span(assoc.def_id).into();
decl.push_span_label(
self.r.tcx.def_span(trait_id),
String::new(),
);
decl
} else {
DUMMY_SP.into()
};
let mut err = self.r.dcx().create_err(
errors::AnonymousLifetimeNonGatReportError {
lifetime: lifetime.ident.span,
decl,
},
);
self.point_at_impl_lifetimes(&mut err, i, lifetime.ident.span);
Expand Down Expand Up @@ -1924,17 +1953,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}

fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) {
let Some((rib, span)) = self.lifetime_ribs[..i]
.iter()
.rev()
.skip(1)
.filter_map(|rib| match rib.kind {
let Some((rib, span)) =
self.lifetime_ribs[..i].iter().rev().find_map(|rib| match rib.kind {
LifetimeRibKind::Generics { span, kind: LifetimeBinderKind::ImplBlock, .. } => {
Some((rib, span))
}
_ => None,
})
.next()
else {
return;
};
Expand All @@ -1956,11 +1981,63 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
);
}
} else {
err.span_label(
span,
"you could add a lifetime on the impl block, if the trait or the self type can \
have one",
);
struct AnonRefFinder;
impl<'ast> Visitor<'ast> for AnonRefFinder {
type Result = ControlFlow<Span>;

fn visit_ty(&mut self, ty: &'ast ast::Ty) -> Self::Result {
if let ast::TyKind::Ref(None, mut_ty) = &ty.kind {
return ControlFlow::Break(mut_ty.ty.span.shrink_to_lo());
}
visit::walk_ty(self, ty)
}

fn visit_lifetime(
&mut self,
lt: &'ast ast::Lifetime,
_cx: visit::LifetimeCtxt,
) -> Self::Result {
if lt.ident.name == kw::UnderscoreLifetime {
return ControlFlow::Break(lt.ident.span);
}
visit::walk_lifetime(self, lt)
}
}

if let Some(ty) = &self.diag_metadata.current_self_type
&& let ControlFlow::Break(sp) = AnonRefFinder.visit_ty(ty)
{
err.multipart_suggestion_verbose(
"add a lifetime to the impl block and use it in the self type and associated \
type",
vec![
(span, "<'a>".to_string()),
(sp, "'a ".to_string()),
(lifetime.shrink_to_hi(), "'a ".to_string()),
],
Applicability::MaybeIncorrect,
);
} else if let Some(item) = &self.diag_metadata.current_item
&& let ItemKind::Impl(impl_) = &item.kind
&& let Some(of_trait) = &impl_.of_trait
&& let ControlFlow::Break(sp) = AnonRefFinder.visit_trait_ref(&of_trait.trait_ref)
{
err.multipart_suggestion_verbose(
"add a lifetime to the impl block and use it in the trait and associated type",
vec![
(span, "<'a>".to_string()),
(sp, "'a".to_string()),
(lifetime.shrink_to_hi(), "'a ".to_string()),
],
Applicability::MaybeIncorrect,
);
} else {
err.span_label(
span,
"you could add a lifetime on the impl block, if the trait or the self type \
could have one",
);
}
}
}

Expand Down Expand Up @@ -3304,6 +3381,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
) {
use crate::ResolutionError::*;
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
let prev = self.diag_metadata.current_impl_item.take();
self.diag_metadata.current_impl_item = Some(&item);
match &item.kind {
AssocItemKind::Const(box ast::ConstItem {
ident,
Expand Down Expand Up @@ -3452,6 +3531,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
panic!("unexpanded macro in resolve!")
}
}
self.diag_metadata.current_impl_item = prev;
}

fn check_trait_item<F>(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ proc-macro = true
# tidy-alphabetical-start
proc-macro2 = "1"
quote = "1"
syn = { version = "2.0.9", features = ["full"] }
syn = { version = "2.0.9", features = ["full", "visit-mut"] }
synstructure = "0.13.0"
# tidy-alphabetical-end
14 changes: 4 additions & 10 deletions tests/mir-opt/const_prop/invalid_constant.main.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,11 @@
StorageDead(_1);
return;
}
+ }
}
+
+ ALLOC0 (size: 4, align: 4) {
+ 00 00 00 00 │ ....
+ }
+ ALLOC0 (size: 4, align: 4) { .. }
+
+ ALLOC1 (size: 4, align: 4) {
+ 04 00 00 00 │ ....
+ }
+ ALLOC1 (size: 4, align: 4) { .. }
+
+ ALLOC2 (size: 4, align: 4) {
+ 01 00 11 00 │ ....
}
+ ALLOC2 (size: 4, align: 4) { .. }

2 changes: 1 addition & 1 deletion tests/mir-opt/const_prop/invalid_constant.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// skip-filecheck
//@ test-mir-pass: GVN
//@ compile-flags: -Zmir-enable-passes=+RemoveZsts
//@ compile-flags: -Zmir-enable-passes=+RemoveZsts -Zdump-mir-exclude-alloc-bytes
// Verify that we can pretty print invalid constants.

#![feature(adt_const_params, unsized_const_params)]
Expand Down
6 changes: 2 additions & 4 deletions tests/mir-opt/const_prop/union.main.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@
StorageDead(_1);
return;
}
+ }
+
+ ALLOC0 (size: 4, align: 4) {
+ 01 00 00 00 │ ....
}
+
+ ALLOC0 (size: 4, align: 4) { .. }

2 changes: 1 addition & 1 deletion tests/mir-opt/const_prop/union.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Tests that we can propagate into places that are projections into unions
//@ test-mir-pass: GVN
//@ compile-flags: -Zinline-mir
//@ compile-flags: -Zinline-mir -Zdump-mir-exclude-alloc-bytes

fn val() -> u32 {
1
Expand Down
6 changes: 2 additions & 4 deletions tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@
StorageDead(_11);
goto -> bb4;
}
+ }
+
+ ALLOC0 (size: 8, align: 4) {
+ 01 00 00 00 __ __ __ __ │ ....░░░░
}
+
+ ALLOC0 (size: 8, align: 4) { .. }

1 change: 1 addition & 0 deletions tests/mir-opt/gvn_loop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@ test-mir-pass: GVN
//@ compile-flags: -Zdump-mir-exclude-alloc-bytes

#![crate_type = "lib"]
#![feature(core_intrinsics, rustc_attrs)]
Expand Down
15 changes: 14 additions & 1 deletion tests/ui/impl-header-lifetime-elision/assoc-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,27 @@ trait MyTrait {

impl MyTrait for &i32 {
type Output = &i32;
//~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
//~^ ERROR missing lifetime in associated type
}

impl MyTrait for &u32 {
type Output = &'_ i32;
//~^ ERROR `'_` cannot be used here
}

impl<'a> MyTrait for &f64 {
type Output = &f64;
//~^ ERROR missing lifetime in associated type
}

trait OtherTrait<'a> {
type Output;
}
impl OtherTrait<'_> for f64 {
type Output = &f64;
//~^ ERROR missing lifetime in associated type
}

// This is what you have to do:
impl<'a> MyTrait for &'a f32 {
type Output = &'a f32;
Expand Down
Loading
Loading