Skip to content

Commit 6a3b69c

Browse files
committed
Auto merge of rust-lang#130888 - cuviper:beta-next, r=cuviper
[beta] backports - Use equality when relating formal and expected type in arg checking rust-lang#129317 - Don't call `extern_crate` when local crate name is the same as a dependency and we have a trait error rust-lang#130275 - bootstrap: Set the dylib path when building books with rustdoc rust-lang#130536 r? cuviper
2 parents 8c27a2b + 1ddfc90 commit 6a3b69c

File tree

10 files changed

+145
-91
lines changed

10 files changed

+145
-91
lines changed

compiler/rustc_hir_typeck/src/callee.rs

+4-17
Original file line numberDiff line numberDiff line change
@@ -503,18 +503,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
503503
let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
504504
let fn_sig = self.normalize(call_expr.span, fn_sig);
505505

506-
// Call the generic checker.
507-
let expected_arg_tys = self.expected_inputs_for_expected_output(
508-
call_expr.span,
509-
expected,
510-
fn_sig.output(),
511-
fn_sig.inputs(),
512-
);
513506
self.check_argument_types(
514507
call_expr.span,
515508
call_expr,
516509
fn_sig.inputs(),
517-
expected_arg_tys,
510+
fn_sig.output(),
511+
expected,
518512
arg_exprs,
519513
fn_sig.c_variadic,
520514
TupleArgumentsFlag::DontTupleArguments,
@@ -866,19 +860,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
866860
// don't know the full details yet (`Fn` vs `FnMut` etc), but we
867861
// do know the types expected for each argument and the return
868862
// type.
869-
870-
let expected_arg_tys = self.expected_inputs_for_expected_output(
871-
call_expr.span,
872-
expected,
873-
fn_sig.output(),
874-
fn_sig.inputs(),
875-
);
876-
877863
self.check_argument_types(
878864
call_expr.span,
879865
call_expr,
880866
fn_sig.inputs(),
881-
expected_arg_tys,
867+
fn_sig.output(),
868+
expected,
882869
arg_exprs,
883870
fn_sig.c_variadic,
884871
TupleArgumentsFlag::TupleArguments,

compiler/rustc_hir_typeck/src/expr.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -1673,15 +1673,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16731673
) {
16741674
let tcx = self.tcx;
16751675

1676-
let expected_inputs =
1677-
self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]);
1678-
let adt_ty_hint = if let Some(expected_inputs) = expected_inputs {
1679-
expected_inputs.get(0).cloned().unwrap_or(adt_ty)
1680-
} else {
1681-
adt_ty
1682-
};
1683-
// re-link the regions that EIfEO can erase.
1684-
self.demand_eqtype(span, adt_ty_hint, adt_ty);
1676+
let adt_ty = self.resolve_vars_with_obligations(adt_ty);
1677+
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
1678+
self.fudge_inference_if_ok(|| {
1679+
let ocx = ObligationCtxt::new(self);
1680+
ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?;
1681+
if !ocx.select_where_possible().is_empty() {
1682+
return Err(TypeError::Mismatch);
1683+
}
1684+
Ok(self.resolve_vars_if_possible(adt_ty))
1685+
})
1686+
.ok()
1687+
});
1688+
if let Some(adt_ty_hint) = adt_ty_hint {
1689+
// re-link the variables that the fudging above can create.
1690+
self.demand_eqtype(span, adt_ty_hint, adt_ty);
1691+
}
16851692

16861693
let ty::Adt(adt, args) = adt_ty.kind() else {
16871694
span_bug!(span, "non-ADT passed to check_expr_struct_fields");

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-38
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons
2020
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
2121
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
2222
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
23-
use rustc_middle::ty::error::TypeError;
2423
use rustc_middle::ty::fold::TypeFoldable;
2524
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
2625
use rustc_middle::ty::{
@@ -36,7 +35,7 @@ use rustc_span::Span;
3635
use rustc_target::abi::FieldIdx;
3736
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
3837
use rustc_trait_selection::traits::{
39-
self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
38+
self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt,
4039
};
4140
use tracing::{debug, instrument};
4241

@@ -689,42 +688,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
689688
vec![ty_error; len]
690689
}
691690

692-
/// Unifies the output type with the expected type early, for more coercions
693-
/// and forward type information on the input expressions.
694-
#[instrument(skip(self, call_span), level = "debug")]
695-
pub(crate) fn expected_inputs_for_expected_output(
696-
&self,
697-
call_span: Span,
698-
expected_ret: Expectation<'tcx>,
699-
formal_ret: Ty<'tcx>,
700-
formal_args: &[Ty<'tcx>],
701-
) -> Option<Vec<Ty<'tcx>>> {
702-
let formal_ret = self.resolve_vars_with_obligations(formal_ret);
703-
let ret_ty = expected_ret.only_has_type(self)?;
704-
705-
let expect_args = self
706-
.fudge_inference_if_ok(|| {
707-
let ocx = ObligationCtxt::new(self);
708-
709-
// Attempt to apply a subtyping relationship between the formal
710-
// return type (likely containing type variables if the function
711-
// is polymorphic) and the expected return type.
712-
// No argument expectations are produced if unification fails.
713-
let origin = self.misc(call_span);
714-
ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?;
715-
if !ocx.select_where_possible().is_empty() {
716-
return Err(TypeError::Mismatch);
717-
}
718-
719-
// Record all the argument types, with the args
720-
// produced from the above subtyping unification.
721-
Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()))
722-
})
723-
.unwrap_or_default();
724-
debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret);
725-
expect_args
726-
}
727-
728691
pub(crate) fn resolve_lang_item_path(
729692
&self,
730693
lang_item: hir::LangItem,

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+49-18
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
1717
use rustc_index::IndexVec;
1818
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
1919
use rustc_middle::ty::adjustment::AllowTwoPhase;
20+
use rustc_middle::ty::error::TypeError;
2021
use rustc_middle::ty::visit::TypeVisitableExt;
2122
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
2223
use rustc_middle::{bug, span_bug};
@@ -25,7 +26,7 @@ use rustc_span::symbol::{kw, Ident};
2526
use rustc_span::{sym, Span, DUMMY_SP};
2627
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
2728
use rustc_trait_selection::infer::InferCtxtExt;
28-
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
29+
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
2930
use tracing::debug;
3031
use {rustc_ast as ast, rustc_hir as hir};
3132

@@ -124,6 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124125
};
125126
if let Err(guar) = has_error {
126127
let err_inputs = self.err_args(args_no_rcvr.len(), guar);
128+
let err_output = Ty::new_error(self.tcx, guar);
127129

128130
let err_inputs = match tuple_arguments {
129131
DontTupleArguments => err_inputs,
@@ -134,28 +136,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
134136
sp,
135137
expr,
136138
&err_inputs,
137-
None,
139+
err_output,
140+
NoExpectation,
138141
args_no_rcvr,
139142
false,
140143
tuple_arguments,
141144
method.ok().map(|method| method.def_id),
142145
);
143-
return Ty::new_error(self.tcx, guar);
146+
return err_output;
144147
}
145148

146149
let method = method.unwrap();
147-
// HACK(eddyb) ignore self in the definition (see above).
148-
let expected_input_tys = self.expected_inputs_for_expected_output(
149-
sp,
150-
expected,
151-
method.sig.output(),
152-
&method.sig.inputs()[1..],
153-
);
154150
self.check_argument_types(
155151
sp,
156152
expr,
157153
&method.sig.inputs()[1..],
158-
expected_input_tys,
154+
method.sig.output(),
155+
expected,
159156
args_no_rcvr,
160157
method.sig.c_variadic,
161158
tuple_arguments,
@@ -175,8 +172,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
175172
call_expr: &'tcx hir::Expr<'tcx>,
176173
// Types (as defined in the *signature* of the target function)
177174
formal_input_tys: &[Ty<'tcx>],
178-
// More specific expected types, after unifying with caller output types
179-
expected_input_tys: Option<Vec<Ty<'tcx>>>,
175+
formal_output: Ty<'tcx>,
176+
// Expected output from the parent expression or statement
177+
expectation: Expectation<'tcx>,
180178
// The expressions for each provided argument
181179
provided_args: &'tcx [hir::Expr<'tcx>],
182180
// Whether the function is variadic, for example when imported from C
@@ -210,6 +208,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
210208
);
211209
}
212210

211+
// First, let's unify the formal method signature with the expectation eagerly.
212+
// We use this to guide coercion inference; it's output is "fudged" which means
213+
// any remaining type variables are assigned to new, unrelated variables. This
214+
// is because the inference guidance here is only speculative.
215+
let formal_output = self.resolve_vars_with_obligations(formal_output);
216+
let expected_input_tys: Option<Vec<_>> = expectation
217+
.only_has_type(self)
218+
.and_then(|expected_output| {
219+
self.fudge_inference_if_ok(|| {
220+
let ocx = ObligationCtxt::new(self);
221+
222+
// Attempt to apply a subtyping relationship between the formal
223+
// return type (likely containing type variables if the function
224+
// is polymorphic) and the expected return type.
225+
// No argument expectations are produced if unification fails.
226+
let origin = self.misc(call_span);
227+
ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
228+
if !ocx.select_where_possible().is_empty() {
229+
return Err(TypeError::Mismatch);
230+
}
231+
232+
// Record all the argument types, with the args
233+
// produced from the above subtyping unification.
234+
Ok(Some(
235+
formal_input_tys
236+
.iter()
237+
.map(|&ty| self.resolve_vars_if_possible(ty))
238+
.collect(),
239+
))
240+
})
241+
.ok()
242+
})
243+
.unwrap_or_default();
244+
213245
let mut err_code = E0061;
214246

215247
// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
@@ -292,21 +324,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
292324

293325
let coerce_error =
294326
self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
295-
296327
if coerce_error.is_some() {
297328
return Compatibility::Incompatible(coerce_error);
298329
}
299330

300-
// 3. Check if the formal type is a supertype of the checked one
301-
// and register any such obligations for future type checks
302-
let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup(
331+
// 3. Check if the formal type is actually equal to the checked one
332+
// and register any such obligations for future type checks.
333+
let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
303334
DefineOpaqueTypes::Yes,
304335
formal_input_ty,
305336
coerced_ty,
306337
);
307338

308339
// If neither check failed, the types are compatible
309-
match supertype_error {
340+
match formal_ty_error {
310341
Ok(InferOk { obligations, value: () }) => {
311342
self.register_predicates(obligations);
312343
Compatibility::Compatible

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
16711671
let name = self.tcx.crate_name(trait_def_id.krate);
16721672
let spans: Vec<_> = [trait_def_id, found_type]
16731673
.into_iter()
1674+
.filter(|def_id| def_id.krate != LOCAL_CRATE)
16741675
.filter_map(|def_id| self.tcx.extern_crate(def_id.krate))
16751676
.map(|data| {
16761677
let dependency = if data.dependency_of == LOCAL_CRATE {

src/bootstrap/src/core/build_steps/doc.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ macro_rules! book {
6363
src: builder.src.join($path),
6464
parent: Some(self),
6565
languages: $lang.into(),
66-
rustdoc: None,
66+
rustdoc_compiler: None,
6767
})
6868
}
6969
}
@@ -113,7 +113,7 @@ impl Step for UnstableBook {
113113
src: builder.md_doc_out(self.target).join("unstable-book"),
114114
parent: Some(self),
115115
languages: vec![],
116-
rustdoc: None,
116+
rustdoc_compiler: None,
117117
})
118118
}
119119
}
@@ -125,7 +125,7 @@ struct RustbookSrc<P: Step> {
125125
src: PathBuf,
126126
parent: Option<P>,
127127
languages: Vec<&'static str>,
128-
rustdoc: Option<PathBuf>,
128+
rustdoc_compiler: Option<Compiler>,
129129
}
130130

131131
impl<P: Step> Step for RustbookSrc<P> {
@@ -157,14 +157,17 @@ impl<P: Step> Step for RustbookSrc<P> {
157157
let _ = fs::remove_dir_all(&out);
158158

159159
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
160-
if let Some(mut rustdoc) = self.rustdoc {
160+
161+
if let Some(compiler) = self.rustdoc_compiler {
162+
let mut rustdoc = builder.rustdoc(compiler);
161163
rustdoc.pop();
162164
let old_path = env::var_os("PATH").unwrap_or_default();
163165
let new_path =
164166
env::join_paths(std::iter::once(rustdoc).chain(env::split_paths(&old_path)))
165167
.expect("could not add rustdoc to PATH");
166168

167169
rustbook_cmd.env("PATH", new_path);
170+
builder.add_rustc_lib_path(compiler, &mut rustbook_cmd);
168171
}
169172

170173
rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).run(builder);
@@ -240,7 +243,7 @@ impl Step for TheBook {
240243
src: absolute_path.clone(),
241244
parent: Some(self),
242245
languages: vec![],
243-
rustdoc: None,
246+
rustdoc_compiler: None,
244247
});
245248

246249
// building older edition redirects
@@ -253,7 +256,7 @@ impl Step for TheBook {
253256
// treat the other editions as not having a parent.
254257
parent: Option::<Self>::None,
255258
languages: vec![],
256-
rustdoc: None,
259+
rustdoc_compiler: None,
257260
});
258261
}
259262

@@ -1218,7 +1221,7 @@ impl Step for RustcBook {
12181221
src: out_base,
12191222
parent: Some(self),
12201223
languages: vec![],
1221-
rustdoc: None,
1224+
rustdoc_compiler: None,
12221225
});
12231226
}
12241227
}
@@ -1252,16 +1255,15 @@ impl Step for Reference {
12521255
// This is needed for generating links to the standard library using
12531256
// the mdbook-spec plugin.
12541257
builder.ensure(compile::Std::new(self.compiler, builder.config.build));
1255-
let rustdoc = builder.rustdoc(self.compiler);
12561258

12571259
// Run rustbook/mdbook to generate the HTML pages.
12581260
builder.ensure(RustbookSrc {
12591261
target: self.target,
12601262
name: "reference".to_owned(),
12611263
src: builder.src.join("src/doc/reference"),
1264+
rustdoc_compiler: Some(self.compiler),
12621265
parent: Some(self),
12631266
languages: vec![],
1264-
rustdoc: Some(rustdoc),
12651267
});
12661268
}
12671269
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ check-pass
2+
3+
// Regression test for for #129286.
4+
// Makes sure that we don't have unconstrained type variables that come from
5+
// bivariant type parameters due to the way that we construct expectation types
6+
// when checking call expressions in HIR typeck.
7+
8+
trait Trait {
9+
type Item;
10+
}
11+
12+
struct Struct<A: Trait<Item = B>, B> {
13+
pub field: A,
14+
}
15+
16+
fn identity<T>(x: T) -> T {
17+
x
18+
}
19+
20+
fn test<A: Trait<Item = B>, B>(x: &Struct<A, B>) {
21+
let x: &Struct<_, _> = identity(x);
22+
}
23+
24+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub struct B;

0 commit comments

Comments
 (0)