Skip to content

Commit 44f8ffe

Browse files
committed
temp
1 parent 2f4d868 commit 44f8ffe

File tree

2 files changed

+162
-106
lines changed

2 files changed

+162
-106
lines changed

src/librustc_typeck/check/autoderef.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc::ty::{ToPredicate, TypeFoldable};
1919
use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
2020

2121
use syntax_pos::Span;
22-
use syntax::ast::{NodeId, Ident};
22+
use syntax::ast::{self, Ident};
2323

2424
use std::iter;
2525

@@ -31,7 +31,7 @@ enum AutoderefKind {
3131

3232
pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> {
3333
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
34-
body_id: NodeId,
34+
body_id: ast::NodeId,
3535
param_env: ty::ParamEnv<'tcx>,
3636
steps: Vec<(Ty<'tcx>, AutoderefKind)>,
3737
cur_ty: Ty<'tcx>,
@@ -107,6 +107,27 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
107107
}
108108

109109
impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
110+
pub fn new(&'a self,
111+
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
112+
param_env: ty::ParamEnv<'tcx>,
113+
body_id: ast::NodeId,
114+
span: Span,
115+
base_ty: Ty<'tcx>)
116+
-> Autoderef<'a, 'gcx, 'tcx>
117+
{
118+
Autoderef {
119+
infcx,
120+
body_id,
121+
param_env,
122+
steps: vec![],
123+
cur_ty: self.resolve_type_vars_if_possible(&base_ty),
124+
obligations: vec![],
125+
at_start: true,
126+
include_raw_pointers: false,
127+
span,
128+
}
129+
}
130+
110131
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
111132
debug!("overloaded_deref_ty({:?})", ty);
112133

@@ -231,17 +252,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
231252

232253
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
233254
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'gcx, 'tcx> {
234-
Autoderef {
235-
infcx: &self.infcx,
236-
body_id: self.body_id,
237-
param_env: self.param_env,
238-
steps: vec![],
239-
cur_ty: self.resolve_type_vars_if_possible(&base_ty),
240-
obligations: vec![],
241-
at_start: true,
242-
include_raw_pointers: false,
243-
span,
244-
}
255+
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
245256
}
246257

247258
pub fn try_overloaded_deref(&self,

src/librustc_typeck/check/method/probe.rs

Lines changed: 138 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -249,33 +249,61 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
249249
{
250250
let mut orig_values = SmallVec::new();
251251
let self_ty = self.infcx.canonicalize_data(&self_ty, &mut orig_values);
252+
// XXX: consider caching this "whole op" here.
252253
let steps = if mode == Mode::MethodCall {
253254
tcx.infer_ctxt().enter(|ref infcx| {
254-
match create_steps(infcx, span, scope_expr_id, self_ty, is_suggestion) {
255-
Some(steps) => Ok(steps),
256-
None => {
257-
return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(),
258-
Vec::new(),
259-
Vec::new(),
260-
None,
261-
mode)))
262-
}
263-
}
264-
})?;
255+
create_steps_inner(infcx, orig_values, self.param_env, span, self_ty)
256+
})
265257
} else {
266-
vec![CandidateStep {
267-
self_ty,
268-
autoderefs: 0,
269-
from_unsafe_deref: false,
270-
unsize: false,
271-
}];
272-
}
273-
274-
let steps =
258+
// XXX: don't make an inference context for nothing here
259+
tcx.infer_ctxt().enter(|ref infcx| {
260+
CreateStepsResult {
261+
steps: vec![CandidateStep {
262+
self_ty: do_make_query_result(infcx, orig_values, self_ty),
263+
autoderefs: 0,
264+
from_unsafe_deref: false,
265+
unsize: false,
266+
}],
267+
bad_ty: None
268+
}
269+
})
270+
};
275271

276-
} else {
272+
if let Some(CreateStepsBadTy { reached_raw_pointer, ty }) = steps.bad_ty {
273+
// Ended in an inference variable. If we are doing
274+
// a real method lookup, this is a hard error because it's
275+
// possible that there will be multiple applicable methods.
276+
if !is_suggestion.0
277+
&& reached_raw_pointer
278+
&& !self.tcx.features().arbitrary_self_types
279+
{
280+
// this case used to be allowed by the compiler,
281+
// so we do a future-compat lint here for the 2015 edition
282+
// (see https://github.com/rust-lang/rust/issues/46906)
283+
if self.tcx.sess.rust_2018() {
284+
span_err!(self.tcx.sess, span, E0699,
285+
"the type of this value must be known \
286+
to call a method on a raw pointer on it");
287+
} else {
288+
self.tcx.lint_node(
289+
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
290+
scope_expr_id,
291+
span,
292+
"type annotations needed");
293+
}
294+
} else {
295+
let ty = self.instantiate_query_result(&orig_values, &ty)
296+
.unwrap_or_else(|| span_bug!(span, "instantiating {:?} failed?", ty));
297+
let t = self.structurally_resolved_type(span, final_ty);
298+
assert_eq!(t, self.tcx.types.err);
299+
return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(),
300+
Vec::new(),
301+
Vec::new(),
302+
None,
303+
mode)));
277304

278-
};
305+
}
306+
}
279307

280308
debug!("ProbeContext: steps for self_ty={:?} are {:?}",
281309
self_ty,
@@ -300,86 +328,103 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
300328
}
301329
}
302330

303-
fn create_steps(&self,
304-
span: Span,
305-
scope_expr_id: ast::NodeId,
306-
self_ty: Ty<'tcx>,
307-
is_suggestion: IsSuggestion)
308-
-> Option<Vec<CandidateStep<'tcx>>> {
309-
// FIXME: we don't need to create the entire steps in one pass
310331

311-
let mut autoderef = self.autoderef(span, self_ty).include_raw_pointers();
332+
fn do_instantiate_query_result<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
333+
param_env: ty::ParamEnv<'tcx>,
334+
inference_vars: CanonicalVarValues<'tcx>,
335+
ty: Ty<'gcx>)
336+
-> Canonical<'gcx, QueryResult<'gcx, Ty<'gcx>>>
337+
{
338+
infcx.canonicalize_response(&QueryResult {
339+
var_values: inference_vars,
340+
region_constraints: vec![],
341+
certainty: Certainity::Proven, // This field is not used by typeck
342+
value: ty,
343+
})
344+
}
345+
}
346+
347+
#[derive(Debug)]
348+
struct CreateStepsResult<'gcx> {
349+
steps: Vec<CandidateStep<'gcx>>,
350+
opt_bad_ty: Option<CreateStepsBadTy<'gcx>>
351+
}
352+
353+
#[derive(Debug)]
354+
struct CreateStepsBadTy<'gcx> {
355+
reached_raw_pointer: bool,
356+
ty: Canonical<'gcx, QueryResult<'gcx, Ty<'gcx>>>,
357+
}
358+
359+
fn do_make_query_result<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
360+
inference_vars: CanonicalVarValues<'tcx>,
361+
ty: Ty<'gcx>)
362+
-> Canonical<'gcx, QueryResult<'gcx, Ty<'gcx>>>
363+
{
364+
infcx.canonicalize_response(&QueryResult {
365+
var_values: inference_vars,
366+
region_constraints: vec![],
367+
certainty: Certainity::Proven, // This field is not used by typeck
368+
value: ty,
369+
})
370+
}
371+
372+
fn create_steps_inner<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
373+
inference_vars: CanonicalVarValues<'tcx>,
374+
param_env: ty::ParamEnv<'tcx>,
375+
span: Span,
376+
self_ty: Canonical<'gcx, Ty<'gcx>>)
377+
-> CreateStepsResult<'gcx>
378+
{
379+
let mut autoderef = Autoderef::new(infcx, param_env, DUMMY_NODE_ID, span, self_ty)
380+
.include_raw_pointers();
312381
let mut reached_raw_pointer = false;
313382
let mut steps: Vec<_> = autoderef.by_ref()
314383
.map(|(ty, d)| {
315-
let step = CandidateStep {
316-
self_ty: ty,
317-
autoderefs: d,
318-
from_unsafe_deref: reached_raw_pointer,
319-
unsize: false,
320-
};
321-
if let ty::RawPtr(_) = ty.sty {
322-
// all the subsequent steps will be from_unsafe_deref
323-
reached_raw_pointer = true;
324-
}
325-
step
384+
let step = CandidateStep {
385+
self_ty: do_make_query_result(infcx, inference_vars, infcx.tcx.mk_slice(ty)),
386+
autoderefs: d,
387+
from_unsafe_deref: reached_raw_pointer,
388+
unsize: false,
389+
};
390+
if let ty::RawPtr(_) = ty.sty {
391+
// all the subsequent steps will be from_unsafe_deref
392+
reached_raw_pointer = true;
393+
}
394+
step
395+
})
396+
.collect();
397+
398+
let final_ty = autoderef.maybe_ambiguous_final_ty();
399+
let opt_bad_ty = match final_ty.sty {
400+
ty::Infer(ty::TyVar(_)) |
401+
ty::Error => {
402+
Some(CreateStepsBadTy {
403+
reached_raw_pointer,
404+
ty: final_ty
326405
})
327-
.collect();
406+
}
407+
ty::Array(elem_ty, _) => {
408+
let dereferences = steps.len() - 1;
409+
410+
steps.push(CandidateStep {
411+
self_ty: do_make_query_result(infcx, inference_vars, infcx.tcx.mk_slice(elem_ty)),
412+
autoderefs: dereferences,
413+
// this could be from an unsafe deref if we had
414+
// a *mut/const [T; N]
415+
from_unsafe_deref: reached_raw_pointer,
416+
unsize: true,
417+
});
328418

329-
let final_ty = autoderef.maybe_ambiguous_final_ty();
330-
match final_ty.sty {
331-
ty::Infer(ty::TyVar(_)) => {
332-
// Ended in an inference variable. If we are doing
333-
// a real method lookup, this is a hard error because it's
334-
// possible that there will be multiple applicable methods.
335-
if !is_suggestion.0 {
336-
if reached_raw_pointer
337-
&& !self.tcx.features().arbitrary_self_types {
338-
// this case used to be allowed by the compiler,
339-
// so we do a future-compat lint here for the 2015 edition
340-
// (see https://github.com/rust-lang/rust/issues/46906)
341-
if self.tcx.sess.rust_2018() {
342-
span_err!(self.tcx.sess, span, E0699,
343-
"the type of this value must be known \
344-
to call a method on a raw pointer on it");
345-
} else {
346-
self.tcx.lint_node(
347-
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
348-
scope_expr_id,
349-
span,
350-
"type annotations needed");
351-
}
352-
} else {
353-
let t = self.structurally_resolved_type(span, final_ty);
354-
assert_eq!(t, self.tcx.types.err);
355-
return None
356-
}
357-
} else {
358-
// If we're just looking for suggestions,
359-
// though, ambiguity is no big thing, we can
360-
// just ignore it.
361-
}
362-
}
363-
ty::Array(elem_ty, _) => {
364-
let dereferences = steps.len() - 1;
365-
366-
steps.push(CandidateStep {
367-
self_ty: self.tcx.mk_slice(elem_ty),
368-
autoderefs: dereferences,
369-
// this could be from an unsafe deref if we had
370-
// a *mut/const [T; N]
371-
from_unsafe_deref: reached_raw_pointer,
372-
unsize: true,
373-
});
374-
}
375-
ty::Error => return None,
376-
_ => (),
419+
None
377420
}
421+
_ => None
422+
}
378423

379-
debug!("create_steps: steps={:?}", steps);
424+
debug!("create_steps: steps={:?} error={:?}", steps, error);
380425

381-
Some(steps)
382-
}
426+
CreateStepsResult { steps, bad_ty }
427+
}
383428

384429

385430
impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

0 commit comments

Comments
 (0)