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 #90862

Closed
wants to merge 14 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
60 changes: 38 additions & 22 deletions compiler/rustc_borrowck/src/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).

use crate::type_check::constraint_conversion::ConstraintConversion;
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::Ty;
use rustc_span::Span;
use rustc_trait_selection::traits::query::normalize::AtExt;
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use rustc_trait_selection::traits::query::Fallible;
use type_op::TypeOpOutput;

use crate::universal_regions::UniversalRegions;

Expand All @@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let (&normalized_output_ty, normalized_input_tys) =
normalized_inputs_and_output.split_last().unwrap();

debug!(?normalized_output_ty);
debug!(?normalized_input_tys);

let mir_def_id = body.source.def_id().expect_local();

// If the user explicitly annotated the input types, extract
Expand Down Expand Up @@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
break;
}

// In MIR, argument N is stored in local N+1.
let local = Local::new(argument_index + 1);

let mir_input_ty = body.local_decls[local].ty;

let mir_input_span = body.local_decls[local].source_info.span;
self.equate_normalized_input_or_output(
normalized_input_ty,
Expand All @@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// If the user explicitly annotated the input types, enforce those.
let user_provided_input_ty =
self.normalize(user_provided_input_ty, Locations::All(mir_input_span));

self.equate_normalized_input_or_output(
user_provided_input_ty,
mir_input_ty,
Expand Down Expand Up @@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
// like to normalize *before* inserting into `local_decls`, but
// doing so ends up causing some other trouble.
let b = match self
.infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.normalize(b)
{
Ok(n) => {
debug!("equate_inputs_and_outputs: {:?}", n);
if n.obligations.iter().all(|o| {
matches!(
o.predicate.kind().skip_binder(),
ty::PredicateKind::RegionOutlives(_)
| ty::PredicateKind::TypeOutlives(_)
)
}) {
n.value
} else {
b
}
}
let b = match self.normalize_and_add_constraints(b) {
Ok(n) => n,
Err(_) => {
debug!("equate_inputs_and_outputs: NoSolution");
b
}
};

// Note: if we have to introduce new placeholders during normalization above, then we won't have
// added those universes to the universe info, which we would want in `relate_tys`.
if let Err(terr) =
Expand All @@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}

pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
let TypeOpOutput { output: norm_ty, constraints, .. } =
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;

debug!("{:?} normalized to {:?}", t, norm_ty);

for data in constraints.into_iter().collect::<Vec<_>>() {
ConstraintConversion::new(
self.infcx,
&self.borrowck_context.universal_regions,
&self.region_bound_pairs,
Some(self.implicit_region_bound),
self.param_env,
Locations::All(DUMMY_SP),
ConstraintCategory::Internal,
&mut self.borrowck_context.constraints,
)
.convert_all(&*data);
}

Ok(norm_ty)
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> {
}

struct BorrowCheckContext<'a, 'tcx> {
universal_regions: &'a UniversalRegions<'tcx>,
pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
location_table: &'a LocationTable,
all_facts: &'a mut Option<AllFacts>,
borrow_set: &'a BorrowSet<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
upvars: &'a [Upvar<'tcx>],
}

Expand Down Expand Up @@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
}

#[instrument(skip(self, category), level = "debug")]
fn eq_types(
&mut self,
expected: Ty<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = rustc_errors::struct_span_err!(
self.sess(),
self_ty.span,
E0783,
E0782,
"{}",
msg,
);
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/formats/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
desc,
parent,
parent_idx: None,
search_type: get_index_search_type(&item, self.tcx),
search_type: get_index_search_type(&item, self.tcx, self.cache),
aliases: item.attrs.get_doc_aliases(),
});
}
Expand Down
40 changes: 23 additions & 17 deletions src/librustdoc/html/render/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
desc,
parent: Some(did),
parent_idx: None,
search_type: get_index_search_type(item, tcx),
search_type: get_index_search_type(item, tcx, cache),
aliases: item.attrs.get_doc_aliases(),
});
}
Expand Down Expand Up @@ -194,17 +194,17 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
crate fn get_index_search_type<'tcx>(
item: &clean::Item,
tcx: TyCtxt<'tcx>,
cache: &Cache,
) -> Option<IndexItemFunctionType> {
let (mut inputs, mut output) = match *item.kind {
clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx),
clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx),
clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx),
clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx, cache),
clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx, cache),
clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx, cache),
_ => return None,
};

inputs.retain(|a| a.ty.name.is_some());
output.retain(|a| a.ty.name.is_some());
let output = if output.is_empty() { None } else { Some(output) };

Some(IndexItemFunctionType { inputs, output })
}
Expand Down Expand Up @@ -254,12 +254,14 @@ crate fn get_real_types<'tcx>(
tcx: TyCtxt<'tcx>,
recurse: usize,
res: &mut Vec<TypeWithKind>,
cache: &Cache,
) {
fn insert_ty(
res: &mut Vec<TypeWithKind>,
tcx: TyCtxt<'_>,
ty: Type,
mut generics: Vec<TypeWithKind>,
_cache: &Cache,
) {
let is_full_generic = ty.is_full_generic();

Expand Down Expand Up @@ -350,23 +352,30 @@ crate fn get_real_types<'tcx>(
continue;
}
if let Some(ty) = x.get_type() {
get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics);
get_real_types(
generics,
&ty,
tcx,
recurse + 1,
&mut ty_generics,
cache,
);
}
}
}
}
insert_ty(res, tcx, arg.clone(), ty_generics);
insert_ty(res, tcx, arg.clone(), ty_generics, cache);
}
// Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
let mut ty_generics = Vec::new();
for bound in bound.get_bounds().unwrap_or(&[]) {
if let Some(path) = bound.get_trait_path() {
let ty = Type::ResolvedPath { did: path.def_id(), path };
get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics);
get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache);
}
}
insert_ty(res, tcx, arg.clone(), ty_generics);
insert_ty(res, tcx, arg.clone(), ty_generics, cache);
}
} else {
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
Expand All @@ -377,10 +386,10 @@ crate fn get_real_types<'tcx>(
let mut ty_generics = Vec::new();
if let Some(arg_generics) = arg.generics() {
for gen in arg_generics.iter() {
get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics);
get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics, cache);
}
}
insert_ty(res, tcx, arg.clone(), ty_generics);
insert_ty(res, tcx, arg.clone(), ty_generics, cache);
}
}

Expand All @@ -392,19 +401,16 @@ crate fn get_all_types<'tcx>(
generics: &Generics,
decl: &FnDecl,
tcx: TyCtxt<'tcx>,
cache: &Cache,
) -> (Vec<TypeWithKind>, Vec<TypeWithKind>) {
let mut all_types = Vec::new();
for arg in decl.inputs.values.iter() {
if arg.type_.is_self_type() {
continue;
}
// FIXME: performance wise, it'd be much better to move `args` declaration outside of the
// loop and replace this line with `args.clear()`.
let mut args = Vec::new();
get_real_types(generics, &arg.type_, tcx, 0, &mut args);
get_real_types(generics, &arg.type_, tcx, 0, &mut args, cache);
if !args.is_empty() {
// FIXME: once back to performance improvements, replace this line with:
// `all_types.extend(args.drain(..));`.
all_types.extend(args);
} else {
if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
Expand All @@ -417,7 +423,7 @@ crate fn get_all_types<'tcx>(
let mut ret_types = Vec::new();
match decl.output {
FnRetTy::Return(ref return_type) => {
get_real_types(generics, return_type, tcx, 0, &mut ret_types);
get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache);
if ret_types.is_empty() {
if let Some(kind) =
return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
Expand Down
21 changes: 8 additions & 13 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ crate struct RenderType {
#[derive(Debug)]
crate struct IndexItemFunctionType {
inputs: Vec<TypeWithKind>,
output: Option<Vec<TypeWithKind>>,
output: Vec<TypeWithKind>,
}

impl Serialize for IndexItemFunctionType {
Expand All @@ -126,21 +126,16 @@ impl Serialize for IndexItemFunctionType {
S: Serializer,
{
// If we couldn't figure out a type, just write `null`.
let mut iter = self.inputs.iter();
if match self.output {
Some(ref output) => iter.chain(output.iter()).any(|i| i.ty.name.is_none()),
None => iter.any(|i| i.ty.name.is_none()),
} {
let has_missing = self.inputs.iter().chain(self.output.iter()).any(|i| i.ty.name.is_none());
if has_missing {
serializer.serialize_none()
} else {
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element(&self.inputs)?;
if let Some(output) = &self.output {
if output.len() > 1 {
seq.serialize_element(&output)?;
} else {
seq.serialize_element(&output[0])?;
}
match self.output.as_slice() {
[] => {}
[one] => seq.serialize_element(one)?,
all => seq.serialize_element(all)?,
}
seq.end()
}
Expand Down Expand Up @@ -2166,7 +2161,7 @@ fn sidebar_deref_methods(
}

// Recurse into any further impls that might exist for `target`
if let Some(target_did) = target.def_id_no_primitives() {
if let Some(target_did) = target.def_id(c) {
if let Some(target_impls) = c.impls.get(&target_did) {
if let Some(target_deref_impl) = target_impls.iter().find(|i| {
i.inner_impl()
Expand Down
7 changes: 4 additions & 3 deletions src/librustdoc/passes/collect_trait_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate

// Follow all `Deref` targets of included items and recursively add them as valid
fn add_deref_target(
cx: &DocContext<'_>,
map: &FxHashMap<DefId, &Type>,
cleaner: &mut BadImplStripper,
type_did: DefId,
Expand All @@ -65,14 +66,14 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
debug!("add_deref_target: type {:?}, target {:?}", type_did, target);
if let Some(target_prim) = target.primitive_type() {
cleaner.prims.insert(target_prim);
} else if let Some(target_did) = target.def_id_no_primitives() {
} else if let Some(target_did) = target.def_id(&cx.cache) {
// `impl Deref<Target = S> for S`
if target_did == type_did {
// Avoid infinite cycles
return;
}
cleaner.items.insert(target_did.into());
add_deref_target(map, cleaner, target_did);
add_deref_target(cx, map, cleaner, target_did);
}
}
}
Expand Down Expand Up @@ -102,7 +103,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
// `Deref` target type and the impl for type positions, this map of types is keyed by
// `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
if cleaner.keep_impl_with_def_id(for_did.into()) {
add_deref_target(&type_did_to_deref_target, &mut cleaner, for_did);
add_deref_target(cx, &type_did_to_deref_target, &mut cleaner, for_did);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Check to see if we can get parameters from an @argsfile file
//
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile-badutf8.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// normalize-stderr-test: "os error \d+" -> "os error $$ERR"
// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile-missing.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Check to see if we can get parameters from an @argsfile file
//
// check-pass
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Check to see if we can get parameters from an @argsfile file
//
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile-badutf8.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Loading