Skip to content
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

Rollup of 6 pull requests #113188

Merged
merged 13 commits into from
Jun 30, 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
7 changes: 4 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&msg_borrow,
None,
);
self.suggest_split_at_mut_if_applicable(
self.suggest_slice_method_if_applicable(
&mut err,
place,
issued_borrow.borrowed_place,
Expand Down Expand Up @@ -1262,7 +1262,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}

fn suggest_split_at_mut_if_applicable(
fn suggest_slice_method_if_applicable(
&self,
err: &mut Diagnostic,
place: Place<'tcx>,
Expand All @@ -1274,7 +1274,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.help(
"consider using `.split_at_mut(position)` or similar method to obtain \
two mutable non-overlapping sub-slices",
);
)
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
}
}

Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
hir_analysis_invalid_union_field_sugg =
wrap the field type in `ManuallyDrop<...>`

hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
.label = const parameter declared here

hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
.label = lifetime declared here

hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
.label = type parameter declared here

hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
.label = lifetimes do not match {$item_kind} in trait
Expand Down
55 changes: 49 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1344,12 +1344,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Binder {
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
} => {
let mut err = self.tcx.sess.struct_span_err(
lifetime_ref.ident.span,
"`impl Trait` can only mention lifetimes bound at the fn or impl level",
);
err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
err.emit();
self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
span: lifetime_ref.ident.span,
param_span: self.tcx.def_span(region_def_id),
});
return;
}
Scope::Root { .. } => break,
Expand Down Expand Up @@ -1379,6 +1377,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let mut late_depth = 0;
let mut scope = self.scope;
let mut crossed_anon_const = false;

let result = loop {
match *scope {
Scope::Body { s, .. } => {
Expand Down Expand Up @@ -1446,6 +1445,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
return;
}

// We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
// AST-based resolution does not care for impl-trait desugaring, which are the
// responsibility of lowering. This may create a mismatch between the resolution
// AST found (`param_def_id`) which points to HRTB, and what HIR allows.
// ```
// fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
// ```
//
// In such case, walk back the binders to diagnose it properly.
let mut scope = self.scope;
loop {
match *scope {
Scope::Binder {
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
} => {
let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
DefKind::TyParam => errors::LateBoundInApit::Type {
span: self.tcx.hir().span(hir_id),
param_span: self.tcx.def_span(param_def_id),
},
DefKind::ConstParam => errors::LateBoundInApit::Const {
span: self.tcx.hir().span(hir_id),
param_span: self.tcx.def_span(param_def_id),
},
kind => {
bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
}
});
self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
return;
}
Scope::Root { .. } => break,
Scope::Binder { s, .. }
| Scope::Body { s, .. }
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. }
| Scope::AnonConstBoundary { s } => {
scope = s;
}
}
}

self.tcx.sess.delay_span_bug(
self.tcx.hir().span(hir_id),
format!("could not resolve {param_def_id:?}"),
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,3 +875,28 @@ pub(crate) enum ReturnTypeNotationIllegalParam {
param_span: Span,
},
}

#[derive(Diagnostic)]
pub(crate) enum LateBoundInApit {
#[diag(hir_analysis_late_bound_type_in_apit)]
Type {
#[primary_span]
span: Span,
#[label]
param_span: Span,
},
#[diag(hir_analysis_late_bound_const_in_apit)]
Const {
#[primary_span]
span: Span,
#[label]
param_span: Span,
},
#[diag(hir_analysis_late_bound_lifetime_in_apit)]
Lifetime {
#[primary_span]
span: Span,
#[label]
param_span: Span,
},
}
24 changes: 15 additions & 9 deletions compiler/rustc_hir_analysis/src/variance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
use rustc_middle::ty::{self, CrateVariancesMap, ImplTraitInTraitData, SubstsRef, Ty, TyCtxt};
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
use std::ops::ControlFlow;

Expand Down Expand Up @@ -51,20 +51,26 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
| DefKind::Struct
| DefKind::Union
| DefKind::Variant
| DefKind::Ctor(..) => {}
| DefKind::Ctor(..) => {
// These are inferred.
let crate_map = tcx.crate_variances(());
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
}
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
return variance_of_opaque(tcx, item_def_id);
}
_ => {
// Variance not relevant.
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item")
DefKind::AssocTy => {
if let Some(ImplTraitInTraitData::Trait { .. }) =
tcx.opt_rpitit_info(item_def_id.to_def_id())
{
return variance_of_opaque(tcx, item_def_id);
}
}
_ => {}
}

// Everything else must be inferred.

let crate_map = tcx.crate_variances(());
crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
// Variance not relevant.
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
}

#[instrument(level = "trace", skip(tcx), ret)]
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
.is_type_alias_impl_trait
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
}
if let DefKind::ImplTraitPlaceholder = def_kind {
self.encode_explicit_item_bounds(def_id);
}
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
{
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,9 +1632,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
..
} = &rib.kind
{
diag.span_help(
*span,
"consider introducing a higher-ranked lifetime here with `for<'a>`",
diag.multipart_suggestion(
"consider introducing a higher-ranked lifetime here",
vec![
(span.shrink_to_lo(), "for<'a> ".into()),
(lifetime.ident.span.shrink_to_hi(), "'a ".into()),
],
Applicability::MachineApplicable,
);
break;
}
Expand Down
17 changes: 10 additions & 7 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ impl CStr {
/// ```
///
/// ```
/// #![feature(const_cstr_methods)]
/// #![feature(const_cstr_from_ptr)]
///
/// use std::ffi::{c_char, CStr};
///
Expand All @@ -256,7 +256,7 @@ impl CStr {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
#[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")]
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
// SAFETY: The caller has provided a pointer that points to a valid C
// string with a NUL terminator of size less than `isize::MAX`, whose
Expand Down Expand Up @@ -377,7 +377,7 @@ impl CStr {
/// assert!(cstr.is_err());
/// ```
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
let nul_pos = memchr::memchr(0, bytes);
match nul_pos {
Expand Down Expand Up @@ -561,10 +561,12 @@ impl CStr {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes(&self) -> &[u8] {
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
pub const fn to_bytes(&self) -> &[u8] {
let bytes = self.to_bytes_with_nul();
// FIXME(const-hack) replace with range index
// SAFETY: to_bytes_with_nul returns slice with length at least 1
unsafe { bytes.get_unchecked(..bytes.len() - 1) }
unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
}

/// Converts this C string to a byte slice containing the trailing 0 byte.
Expand All @@ -588,7 +590,7 @@ impl CStr {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
pub const fn to_bytes_with_nul(&self) -> &[u8] {
// SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
// is safe on all supported targets.
Expand All @@ -612,7 +614,8 @@ impl CStr {
/// assert_eq!(cstr.to_str(), Ok("foo"));
/// ```
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
// instead of in `from_ptr()`, it may be worth considering if this should
// be rewritten to do the UTF-8 check inline with the length calculation
Expand Down
1 change: 0 additions & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_char_from_u32_unchecked)]
#![feature(const_cstr_methods)]
#![feature(const_discriminant)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
Expand Down
7 changes: 3 additions & 4 deletions tests/ui/error-codes/E0637.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
LL | T: Into<&u32>,
| ^ explicit lifetime name needed here
|
help: consider introducing a higher-ranked lifetime here with `for<'a>`
--> $DIR/E0637.rs:13:8
help: consider introducing a higher-ranked lifetime here
|
LL | T: Into<&u32>,
| ^
LL | T: for<'a> Into<&'a u32>,
| +++++++ ++

error: aborting due to 3 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
LL | fn should_error<T>() where T : Into<&u32> {}
| ^ explicit lifetime name needed here
|
help: consider introducing a higher-ranked lifetime here with `for<'a>`
--> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32
help: consider introducing a higher-ranked lifetime here
|
LL | fn should_error<T>() where T : Into<&u32> {}
| ^
LL | fn should_error<T>() where T : for<'a> Into<&'a u32> {}
| +++++++ ++

error[E0106]: missing lifetime specifier
--> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/in-trait/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ impl Foo for Local {
fn bar(self) -> Arc<String> { Arc::new(String::new()) }
}

fn generic(f: impl Foo) {
let x = &*f.bar();
}

fn main() {
// Witness an RPITIT from another crate.
let &() = Foreign.bar();
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/impl-trait/in-trait/variances-of-gat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// check-pass
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
// revisions: current next

#![feature(return_position_impl_trait_in_trait)]

trait Foo {}

impl Foo for () {}

trait ThreeCellFragment {
fn ext_cells<'a>(&'a self) -> impl Foo + 'a {
self.ext_adjacent_cells()
}

fn ext_adjacent_cells<'a>(&'a self) -> impl Foo + 'a;
}

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/universal_wrong_hrtb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ trait Trait<'a> {
}

fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
//~^ ERROR `impl Trait` can only mention lifetimes from an fn or impl

fn main() {}
10 changes: 2 additions & 8 deletions tests/ui/impl-trait/universal_wrong_hrtb.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error: `impl Trait` can only mention lifetimes bound at the fn or impl level
error: `impl Trait` can only mention lifetimes from an fn or impl
--> $DIR/universal_wrong_hrtb.rs:5:73
|
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
| ^^
|
note: lifetime declared here
--> $DIR/universal_wrong_hrtb.rs:5:39
|
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
| ^^
| -- lifetime declared here ^^

error: aborting due to previous error

1 change: 1 addition & 0 deletions tests/ui/suggestions/suggest-split-at-mut.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ LL | *a = 5;
| ------ first borrow later used here
|
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
= help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete

trait Trait<Input> {
type Assoc;
}

fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl

fn main() {}
Loading