Auto merge of #129317 - compiler-errors:expectation-subtyping, r=lcnr · rust-lang/rust-clippy@bd53aa3 (original) (raw)

`@@ -17,6 +17,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;

`

17

17

`use rustc_index::IndexVec;

`

18

18

`use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};

`

19

19

`use rustc_middle::ty::adjustment::AllowTwoPhase;

`

``

20

`+

use rustc_middle::ty::error::TypeError;

`

20

21

`use rustc_middle::ty::visit::TypeVisitableExt;

`

21

22

`use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};

`

22

23

`use rustc_middle::{bug, span_bug};

`

`@@ -25,7 +26,7 @@ use rustc_span::symbol::{kw, Ident};

`

25

26

`use rustc_span::{sym, Span, DUMMY_SP};

`

26

27

`use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};

`

27

28

`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};

`

29

30

`use tracing::debug;

`

30

31

`use {rustc_ast as ast, rustc_hir as hir};

`

31

32

``

`@@ -124,6 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

124

125

`};

`

125

126

`if let Err(guar) = has_error {

`

126

127

`let err_inputs = self.err_args(args_no_rcvr.len(), guar);

`

``

128

`+

let err_output = Ty::new_error(self.tcx, guar);

`

127

129

``

128

130

`let err_inputs = match tuple_arguments {

`

129

131

`DontTupleArguments => err_inputs,

`

`@@ -134,28 +136,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

134

136

` sp,

`

135

137

` expr,

`

136

138

`&err_inputs,

`

137

``

`-

None,

`

``

139

`+

err_output,

`

``

140

`+

NoExpectation,

`

138

141

` args_no_rcvr,

`

139

142

`false,

`

140

143

` tuple_arguments,

`

141

144

` method.ok().map(|method| method.def_id),

`

142

145

`);

`

143

``

`-

return Ty::new_error(self.tcx, guar);

`

``

146

`+

return err_output;

`

144

147

`}

`

145

148

``

146

149

`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

``

`-

);

`

154

150

`self.check_argument_types(

`

155

151

` sp,

`

156

152

` expr,

`

157

153

`&method.sig.inputs()[1..],

`

158

``

`-

expected_input_tys,

`

``

154

`+

method.sig.output(),

`

``

155

`+

expected,

`

159

156

` args_no_rcvr,

`

160

157

` method.sig.c_variadic,

`

161

158

` tuple_arguments,

`

`@@ -175,8 +172,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

175

172

`call_expr: &'tcx hir::Expr<'tcx>,

`

176

173

`// Types (as defined in the signature of the target function)

`

177

174

`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>,

`

180

178

`// The expressions for each provided argument

`

181

179

`provided_args: &'tcx [hir::Expr<'tcx>],

`

182

180

`// Whether the function is variadic, for example when imported from C

`

`@@ -210,6 +208,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

210

208

`);

`

211

209

`}

`

212

210

``

``

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

+

213

245

`let mut err_code = E0061;

`

214

246

``

215

247

`// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here

`

`@@ -292,21 +324,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

292

324

``

293

325

`let coerce_error =

`

294

326

`self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();

`

295

``

-

296

327

`if coerce_error.is_some() {

`

297

328

`return Compatibility::Incompatible(coerce_error);

`

298

329

`}

`

299

330

``

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(

`

303

334

`DefineOpaqueTypes::Yes,

`

304

335

` formal_input_ty,

`

305

336

` coerced_ty,

`

306

337

`);

`

307

338

``

308

339

`// If neither check failed, the types are compatible

`

309

``

`-

match supertype_error {

`

``

340

`+

match formal_ty_error {

`

310

341

`Ok(InferOk { obligations, value: () }) => {

`

311

342

`self.register_predicates(obligations);

`

312

343

`Compatibility::Compatible

`