Skip to content

Rollup of 6 pull requests #114358

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

Merged
merged 16 commits into from
Aug 2, 2023
Merged
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
2 changes: 1 addition & 1 deletion compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn rust_version_symbol() -> Symbol {
}

pub fn is_builtin_attr(attr: &Attribute) -> bool {
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
}

enum AttrError {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2133,13 +2133,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.current -= 1;
}
fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) {
if self.span == expr.span {
if self.span == expr.span.source_callsite() {
self.found = self.current;
}
walk_expr(self, expr);
}
}
let source_info = self.body.source_info(location);
let proper_span = proper_span.source_callsite();
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
&& let Some(node) = self.infcx.tcx.hir().find(scope_data.lint_root)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let traits: Vec<_> =
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);

// Don't print `TyErr` to the user.
// Don't print `ty::Error` to the user.
self.report_ambiguous_associated_type(
span,
&[qself_ty.to_string()],
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,8 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
for (region_a, region_a_idx) in &regions {
// Ignore `'static` lifetimes for the purpose of this lint: it's
// because we know it outlives everything and so doesn't give meaningful
// clues
if let ty::ReStatic = **region_a {
// clues. Also ignore `ReError`, to avoid knock-down errors.
if let ty::ReStatic | ty::ReError(_) = **region_a {
continue;
}
// For each region argument (e.g., `'a` in our example), check for a
Expand Down Expand Up @@ -599,8 +599,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// on the GAT itself.
for (region_b, region_b_idx) in &regions {
// Again, skip `'static` because it outlives everything. Also, we trivially
// know that a region outlives itself.
if ty::ReStatic == **region_b || region_a == region_b {
// know that a region outlives itself. Also ignore `ReError`, to avoid
// knock-down errors.
if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b {
continue;
}
if region_known_to_outlive(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

/// Converts the types that the user supplied, in case that doing
/// so should yield an error, but returns back a signature where
/// all parameters are of type `TyErr`.
/// all parameters are of type `ty::Error`.
fn error_sig_of_closure(
&self,
decl: &hir::FnDecl<'_>,
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2567,15 +2567,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
None,
);
if let Some(infer::RelateParamBound(_, t, _)) = origin {
let return_impl_trait =
self.tcx.return_type_impl_trait(generic_param_scope).is_some();
let t = self.resolve_vars_if_possible(t);
match t.kind() {
// We've got:
// fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
// suggest:
// fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
ty::Closure(..) | ty::Alias(ty::Opaque, ..) if return_impl_trait => {
ty::Closure(..) | ty::Alias(ty::Opaque, ..) => {
new_binding_suggestion(&mut err, type_param_span);
}
_ => {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
generic_ty: Ty<'tcx>,
min: ty::Region<'tcx>,
) -> bool {
if let ty::ReError(_) = *min {
return true;
}

match bound {
VerifyBound::IfEq(verify_if_eq_b) => {
let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ rustc_queries! {
separate_provide_extern
}

query adt_sized_constraint(key: DefId) -> &'tcx [Ty<'tcx>] {
query adt_sized_constraint(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
desc { |tcx| "computing `Sized` constraints for `{}`", tcx.def_path_str(key) }
}

Expand Down
16 changes: 4 additions & 12 deletions compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,18 +562,10 @@ impl<'tcx> AdtDef<'tcx> {
tcx.adt_destructor(self.did())
}

/// Returns a list of types such that `Self: Sized` if and only
/// if that type is `Sized`, or `TyErr` if this type is recursive.
///
/// Oddly enough, checking that the sized-constraint is `Sized` is
/// actually more expressive than checking all members:
/// the `Sized` trait is inductive, so an associated type that references
/// `Self` would prevent its containing ADT from being `Sized`.
///
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did()))
/// Returns a list of types such that `Self: Sized` if and only if that
/// type is `Sized`, or `ty::Error` if this type has a recursive layout.
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
tcx.adt_sized_constraint(self.did())
}
}

Expand Down
29 changes: 1 addition & 28 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
};
use rustc_hir::{Constness, HirId, Node, TraitCandidate};
use rustc_index::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::dep_graph::DepNodeIndex;
Expand Down Expand Up @@ -1077,31 +1075,6 @@ impl<'tcx> TyCtxt<'tcx> {
return None;
}

pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
// `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
match self.hir().get_by_def_id(scope_def_id) {
Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
_ => return None,
}

let ret_ty = self.type_of(scope_def_id).instantiate_identity();
match ret_ty.kind() {
ty::FnDef(_, _) => {
let sig = ret_ty.fn_sig(self);
let output = self.erase_late_bound_regions(sig.output());
output.is_impl_trait().then(|| {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
(output, fn_decl.output.span())
})
}
_ => None,
}
}

/// Checks if the bound region is in Impl Item.
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
let container_id = self.parent(suitable_region_binding_scope.to_def_id());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(

ty::Adt(def, args) => {
let sized_crit = def.sized_constraint(ecx.tcx());
Ok(sized_crit.iter_instantiated_copied(ecx.tcx(), args).collect())
Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect())
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,10 @@ fn rematch_unsize<'tcx>(
goal.param_env,
&mut nested,
);

match (a_ty.kind(), b_ty.kind()) {
// Don't try to coerce `?0` to `dyn Trait`
(ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => Ok(None),
// Stall any ambiguous upcasting goals, since we can't rematch those
(ty::Dynamic(_, _, ty::Dyn), ty::Dynamic(_, _, ty::Dyn)) => match certainty {
Certainty::Yes => Ok(Some(ImplSource::Builtin(source, nested))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3030,8 +3030,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err);
}

self.maybe_suggest_convert_to_slice(
self.suggest_convert_to_slice(
err,
obligation,
trait_ref,
impl_candidates.as_slice(),
span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,10 @@ pub trait TypeErrCtxtExt<'tcx> {
param_env: ty::ParamEnv<'tcx>,
) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;

fn maybe_suggest_convert_to_slice(
fn suggest_convert_to_slice(
&self,
err: &mut Diagnostic,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
Expand Down Expand Up @@ -3944,13 +3945,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// If the type that failed selection is an array or a reference to an array,
/// but the trait is implemented for slices, suggest that the user converts
/// the array into a slice.
fn maybe_suggest_convert_to_slice(
fn suggest_convert_to_slice(
&self,
err: &mut Diagnostic,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
) {
// We can only suggest the slice coersion for function arguments since the suggestion
// would make no sense in turbofish or call
let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else {
return;
};

// Three cases where we can make a suggestion:
// 1. `[T; _]` (array of T)
// 2. `&[T; _]` (reference to array of T)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2099,7 +2099,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
Where(
obligation
.predicate
.rebind(sized_crit.iter_instantiated_copied(self.tcx(), args).collect()),
.rebind(sized_crit.iter_instantiated(self.tcx(), args).collect()),
)
}

Expand Down
26 changes: 18 additions & 8 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn sized_constraint_for_ty<'tcx>(
let adt_tys = adt.sized_constraint(tcx);
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
adt_tys
.iter_instantiated_copied(tcx, args)
.iter_instantiated(tcx, args)
.flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
.collect()
}
Expand All @@ -58,11 +58,18 @@ fn sized_constraint_for_ty<'tcx>(
// we know that `T` is Sized and do not need to check
// it on the impl.

let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] };
let sized_predicate =
ty::TraitRef::new(tcx, sized_trait, [ty]).without_const().to_predicate(tcx);
let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() else { return vec![ty] };
let predicates = tcx.predicates_of(adtdef.did()).predicates;
if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
if predicates.iter().any(|(p, _)| {
p.as_trait_clause().is_some_and(|trait_pred| {
trait_pred.def_id() == sized_trait_def_id
&& trait_pred.self_ty().skip_binder() == ty
})
}) {
vec![]
} else {
vec![ty]
}
}

Placeholder(..) | Bound(..) | Infer(..) => {
Expand Down Expand Up @@ -92,10 +99,13 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
/// - a tuple of type parameters or projections, if there are multiple
/// such.
/// - an Error, if a type is infinitely sized
fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
fn adt_sized_constraint<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
if let Some(def_id) = def_id.as_local() {
if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
return tcx.mk_type_list(&[Ty::new_misc_error(tcx)]);
return ty::EarlyBinder::bind(tcx.mk_type_list(&[Ty::new_misc_error(tcx)]));
}
}
let def = tcx.adt_def(def_id);
Expand All @@ -107,7 +117,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {

debug!("adt_sized_constraint: {:?} => {:?}", def, result);

result
ty::EarlyBinder::bind(result)
}

/// See `ParamEnv` struct definition for details.
Expand Down
6 changes: 5 additions & 1 deletion tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ LL | let x = defer(&vec!["Goodbye", "world!"]);
LL | x.x[0];
| ------ borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = vec!["Goodbye", "world!"];
LL ~ let x = defer(&binding);
|

error: aborting due to previous error

Expand Down
13 changes: 13 additions & 0 deletions tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait Test {}
impl Test for &[u8] {}

fn needs_test<T: Test>() -> T {
panic!()
}

fn main() {
needs_test::<[u8; 1]>();
//~^ ERROR the trait bound
let x: [u8; 1] = needs_test();
//~^ ERROR the trait bound
}
29 changes: 29 additions & 0 deletions tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:9:18
|
LL | needs_test::<[u8; 1]>();
| ^^^^^^^ the trait `Test` is not implemented for `[u8; 1]`
|
= help: the trait `Test` is implemented for `&[u8]`
note: required by a bound in `needs_test`
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:4:18
|
LL | fn needs_test<T: Test>() -> T {
| ^^^^ required by this bound in `needs_test`

error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:11:22
|
LL | let x: [u8; 1] = needs_test();
| ^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]`
|
= help: the trait `Test` is implemented for `&[u8]`
note: required by a bound in `needs_test`
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:4:18
|
LL | fn needs_test<T: Test>() -> T {
| ^^^^ required by this bound in `needs_test`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(return_position_impl_trait_in_trait)]

trait Iterable {
type Item<'a>
where
Self: 'a;

fn iter(&self) -> impl Iterator<Item = Self::Item<'missing>>;
//~^ ERROR use of undeclared lifetime name `'missing`
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0261]: use of undeclared lifetime name `'missing`
--> $DIR/missing-lt-outlives-in-rpitit-114274.rs:8:55
|
LL | fn iter(&self) -> impl Iterator<Item = Self::Item<'missing>>;
| ^^^^^^^^ undeclared lifetime
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'missing` lifetime
|
LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>>;
| +++++++++++++
help: consider introducing lifetime `'missing` here
|
LL | fn iter<'missing>(&self) -> impl Iterator<Item = Self::Item<'missing>>;
| ++++++++++
help: consider introducing lifetime `'missing` here
|
LL | trait Iterable<'missing> {
| ++++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0261`.
Loading