Skip to content

Commit

Permalink
Auto merge of rust-lang#126037 - matthiaskrgr:rollup-7pz1nhr, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 10 pull requests

Successful merges:

 - rust-lang#124746 (`rustc --explain E0582` additional example)
 - rust-lang#125407 (Detect when user is trying to create a lending `Iterator` and give a custom explanation)
 - rust-lang#125505 (Add intra-doc-links to rustc_middle crate-level docs.)
 - rust-lang#125792 (Don't drop `Unsize` candidate in intercrate mode)
 - rust-lang#125819 (Various `HirTyLowerer` cleanups)
 - rust-lang#125861 (rustc_codegen_ssa: fix `get_rpath_relative_to_output` panic when lib only contains file name)
 - rust-lang#125911 (delete bootstrap build before switching to bumped rustc)
 - rust-lang#125921 (coverage: Carve out hole spans in a separate early pass)
 - rust-lang#125940 (std::unix::fs::get_path: using fcntl codepath for netbsd instead.)
 - rust-lang#126022 (set `has_unconstrained_ty_var` when generalizing aliases in bivariant contexts)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 5, 2024
2 parents c1dba09 + dd2e1a3 commit 7ebd2bd
Show file tree
Hide file tree
Showing 32 changed files with 755 additions and 382 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/rpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsStrin
// Strip filenames
let lib = lib.parent().unwrap();
let output = config.out_filename.parent().unwrap();

// If output or lib is empty, just assume it locates in current path
let lib = if lib == Path::new("") { Path::new(".") } else { lib };
let output = if output == Path::new("") { Path::new(".") } else { output };

let lib = try_canonicalize(lib).unwrap();
let output = try_canonicalize(output).unwrap();
let relative = path_relative_from(&lib, &output)
Expand Down
16 changes: 16 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ fn test_rpath_relative() {
}
}

#[test]
fn test_rpath_relative_issue_119571() {
let config = &mut RPathConfig {
libs: &[],
out_filename: PathBuf::from("rustc"),
has_rpath: true,
is_like_osx: false,
linker_is_gnu: true,
};
// Should not panic when out_filename only contains filename.
// Issue 119571
let _ = get_rpath_relative_to_output(config, Path::new("lib/libstd.so"));
// Should not panic when lib only contains filename.
let _ = get_rpath_relative_to_output(config, Path::new("libstd.so"));
}

#[test]
fn test_xlinker() {
let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]);
Expand Down
34 changes: 34 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0582.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,40 @@ fn bar<F, G>(t: F, u: G)
fn main() { }
```

This error also includes the use of associated types with lifetime parameters.
```compile_fail,E0582
trait Foo {
type Assoc<'a>;
}
struct Bar<X, F>
where
X: Foo,
F: for<'a> Fn(X::Assoc<'a>) -> &'a i32
{
x: X,
f: F
}
```
The latter scenario encounters this error because `Foo::Assoc<'a>` could be
implemented by a type that does not use the `'a` parameter, so there is no
guarentee that `X::Assoc<'a>` actually uses `'a`.

To fix this we can pass a dummy parameter:
```
# trait Foo {
# type Assoc<'a>;
# }
struct Bar<X, F>
where
X: Foo,
F: for<'a> Fn(X::Assoc<'a>, /* dummy */ &'a ()) -> &'a i32
{
x: X,
f: F
}
```

Note: The examples above used to be (erroneously) accepted by the
compiler, but this was since corrected. See [issue #33685] for more
details.
Expand Down
117 changes: 105 additions & 12 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ use rustc_ast::Recovered;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, E0228};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::intravisit::{self, walk_generics, Visitor};
use rustc_hir::{self as hir};
use rustc_hir::{GenericParamKind, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
Expand All @@ -44,7 +44,7 @@ use std::ops::Bound;

use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::errors;
use crate::hir_ty_lowering::HirTyLowerer;
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
pub use type_of::test_opaque_hidden_types;

mod generics_of;
Expand Down Expand Up @@ -370,16 +370,26 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
self.tcx
}

fn item_def_id(&self) -> DefId {
self.item_def_id.to_def_id()
fn item_def_id(&self) -> LocalDefId {
self.item_def_id
}

fn allow_infer(&self) -> bool {
false
}

fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
None
fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
if let RegionInferReason::BorrowedObjectLifetimeDefault = reason {
let e = struct_span_code_err!(
self.tcx().dcx(),
span,
E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound"
)
.emit();
self.set_tainted_by_errors(e);
ty::Region::new_error(self.tcx(), e)
} else {
// This indicates an illegal lifetime in a non-assoc-trait position
ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
}
}

fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
Expand Down Expand Up @@ -510,6 +520,89 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
self.tainted_by_errors.set(Some(err));
}

fn lower_fn_sig(
&self,
decl: &hir::FnDecl<'tcx>,
generics: Option<&hir::Generics<'_>>,
hir_id: rustc_hir::HirId,
hir_ty: Option<&hir::Ty<'_>>,
) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
let tcx = self.tcx();
// We proactively collect all the inferred type params to emit a single error per fn def.
let mut visitor = HirPlaceholderCollector::default();
let mut infer_replacements = vec![];

if let Some(generics) = generics {
walk_generics(&mut visitor, generics);
}

let input_tys = decl
.inputs
.iter()
.enumerate()
.map(|(i, a)| {
if let hir::TyKind::Infer = a.kind {
if let Some(suggested_ty) =
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
{
infer_replacements.push((a.span, suggested_ty.to_string()));
return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
}
}

// Only visit the type looking for `_` if we didn't fix the type above
visitor.visit_ty(a);
self.lowerer().lower_arg_ty(a, None)
})
.collect();

let output_ty = match decl.output {
hir::FnRetTy::Return(output) => {
if let hir::TyKind::Infer = output.kind
&& let Some(suggested_ty) =
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
{
infer_replacements.push((output.span, suggested_ty.to_string()));
Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
} else {
visitor.visit_ty(output);
self.lower_ty(output)
}
}
hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
};

if !(visitor.0.is_empty() && infer_replacements.is_empty()) {
// We check for the presence of
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.

let mut diag = crate::collect::placeholder_type_error_diag(
tcx,
generics,
visitor.0,
infer_replacements.iter().map(|(s, _)| *s).collect(),
true,
hir_ty,
"function",
);

if !infer_replacements.is_empty() {
diag.multipart_suggestion(
format!(
"try replacing `_` with the type{} in the corresponding trait method signature",
rustc_errors::pluralize!(infer_replacements.len()),
),
infer_replacements,
Applicability::MachineApplicable,
);
}

self.set_tainted_by_errors(diag.emit());
}

(input_tys, output_ty)
}
}

/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
Expand Down
14 changes: 8 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason};
use hir::{HirId, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
Expand Down Expand Up @@ -117,7 +117,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let mut is_trait = None;
let mut is_default_impl_trait = None;

// FIXME: Should ItemCtxt take a LocalDefId?
let icx = ItemCtxt::new(tcx, def_id);

const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
Expand Down Expand Up @@ -244,12 +243,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}

hir::WherePredicate::RegionPredicate(region_pred) => {
let r1 = icx.lowerer().lower_lifetime(region_pred.lifetime, None);
let r1 = icx
.lowerer()
.lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
predicates.extend(region_pred.bounds.iter().map(|bound| {
let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => {
(icx.lowerer().lower_lifetime(lt, None), lt.ident.span)
}
hir::GenericBound::Outlives(lt) => (
icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
lt.ident.span,
),
bound => {
span_bug!(
bound.span(),
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use crate::bounds::Bounds;
use crate::errors;
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};

use super::RegionInferReason;

impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Add a `Sized` bound to the `bounds` if appropriate.
///
Expand Down Expand Up @@ -166,7 +168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
}
hir::GenericBound::Outlives(lifetime) => {
let region = self.lower_lifetime(lifetime, None);
let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
bounds.push_region_bound(
self.tcx(),
ty::Binder::bind_with_vars(
Expand Down
Loading

0 comments on commit 7ebd2bd

Please sign in to comment.