Skip to content

Change default type parameters to match the behavior specified in the RFC #27761

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

Closed
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
40 changes: 26 additions & 14 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,40 +616,52 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

/// Returns a type variable's default fallback if any exists. A default
/// must be attached to the variable when created, if it is created
/// without a default, this will return None.
/// without a default, this will return NoDefault.
///
/// This code does not apply to integral or floating point variables,
/// only to use declared defaults.
///
/// See `new_ty_var_with_default` to create a type variable with a default.
/// See `type_variable::Default` for details about what a default entails.
pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
pub fn default(&self, ty: Ty<'tcx>) -> type_variable::Default<'tcx> {
match ty.sty {
ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid),
_ => None
ty::TyInfer(ty::TyVar(vid)) => self.type_variables
.borrow()
.default(vid)
.clone(),
_ => type_variable::Default::None,
}
}

pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> {
// Returns a vector containing all type variables that have an applicable default,
// along with their defaults.
//
// NB: You must be careful to only apply defaults once, if a variable is unififed
// it many no longer be unsolved and apply a second default will mostly likely
// result in a type error.
pub fn candidates_for_defaulting(&self)
-> Vec<(ty::Ty<'tcx>, type_variable::Default<'tcx>)> {
let mut variables = Vec::new();

let unbound_ty_vars = self.type_variables
.borrow()
.unsolved_variables()
.candidates_for_defaulting()
.into_iter()
.map(|t| self.tcx.mk_var(t));
.map(|(t, d)| (self.tcx.mk_var(t), d));

let unbound_int_vars = self.int_unification_table
.borrow_mut()
.unsolved_variables()
.into_iter()
.map(|v| self.tcx.mk_int_var(v));
.map(|v| (self.tcx.mk_int_var(v),
type_variable::Default::Integer));

let unbound_float_vars = self.float_unification_table
.borrow_mut()
.unsolved_variables()
.into_iter()
.map(|v| self.tcx.mk_float_var(v));
.map(|v| (self.tcx.mk_float_var(v),
type_variable::Default::Float));

variables.extend(unbound_ty_vars);
variables.extend(unbound_int_vars);
Expand Down Expand Up @@ -960,7 +972,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

pub fn next_ty_var_with_default(&self,
default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
default: Option<type_variable::UserDefault<'tcx>>) -> Ty<'tcx> {
let ty_var_id = self.type_variables
.borrow_mut()
.new_var(false, default);
Expand Down Expand Up @@ -1013,7 +1025,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

for def in defs.iter() {
let default = def.default.map(|default| {
type_variable::Default {
type_variable::UserDefault {
ty: default.subst_spanned(self.tcx, substs, Some(span)),
origin_span: span,
def_id: def.default_def_id
Expand Down Expand Up @@ -1319,13 +1331,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

pub fn report_conflicting_default_types(&self,
span: Span,
expected: type_variable::Default<'tcx>,
actual: type_variable::Default<'tcx>) {
expected: type_variable::UserDefault<'tcx>,
actual: type_variable::UserDefault<'tcx>) {
let trace = TypeTrace {
origin: Misc(span),
values: Types(ExpectedFound {
expected: expected.ty,
found: actual.ty
found: actual.ty,
})
};

Expand Down
83 changes: 53 additions & 30 deletions src/librustc/middle/infer/type_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,30 @@ pub struct TypeVariableTable<'tcx> {

struct TypeVariableData<'tcx> {
value: TypeVariableValue<'tcx>,
diverging: bool
default: Default<'tcx>,
}

enum TypeVariableValue<'tcx> {
Known(Ty<'tcx>),
Bounded {
relations: Vec<Relation>,
default: Option<Default<'tcx>>
}
}

// We will use this to store the required information to recapitulate what happened when
// an error occurs.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Default<'tcx> {
pub enum Default<'tcx> {
User(UserDefault<'tcx>),
Integer,
Float,
Diverging,
None,
}

// We will use this to store the required information to recapitulate
// what happened when an error occurs.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct UserDefault<'tcx> {
/// The default type provided by the user
pub ty: Ty<'tcx>,
/// The span where the default was incurred
pub origin_span: Span,
Expand All @@ -53,9 +62,9 @@ pub struct Snapshot {
snapshot: sv::Snapshot
}

enum UndoEntry<'tcx> {
enum UndoEntry {
// The type of the var was specified.
SpecifyVar(ty::TyVid, Vec<Relation>, Option<Default<'tcx>>),
SpecifyVar(ty::TyVid, Vec<Relation>),
Relate(ty::TyVid, ty::TyVid),
}

Expand Down Expand Up @@ -88,15 +97,15 @@ impl<'tcx> TypeVariableTable<'tcx> {
relations(self.values.get_mut(a.index as usize))
}

pub fn default(&self, vid: ty::TyVid) -> Option<Default<'tcx>> {
match &self.values.get(vid.index as usize).value {
&Known(_) => None,
&Bounded { ref default, .. } => default.clone()
}
pub fn default(&self, vid: ty::TyVid) -> &Default<'tcx> {
&self.values.get(vid.index as usize).default
}

pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
self.values.get(vid.index as usize).diverging
match self.values.get(vid.index as usize).default {
Default::Diverging => true,
_ => false,
}
}

/// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
Expand Down Expand Up @@ -124,8 +133,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
mem::replace(value_ptr, Known(ty))
};

let (relations, default) = match old_value {
Bounded { relations, default } => (relations, default),
let relations = match old_value {
Bounded { relations } => relations ,
Known(_) => panic!("Asked to instantiate variable that is \
already instantiated")
};
Expand All @@ -134,16 +143,24 @@ impl<'tcx> TypeVariableTable<'tcx> {
stack.push((ty, dir, vid));
}

self.values.record(SpecifyVar(vid, relations, default));
self.values.record(SpecifyVar(vid, relations));
}

pub fn new_var(&mut self,
diverging: bool,
default: Option<Default<'tcx>>) -> ty::TyVid {
default: Option<UserDefault<'tcx>>) -> ty::TyVid {
let default = if diverging {
Default::Diverging
} else {
default.map(|u| Default::User(u))
.unwrap_or(Default::None)
};

let index = self.values.push(TypeVariableData {
value: Bounded { relations: vec![], default: default },
diverging: diverging
value: Bounded { relations: vec![] },
default: default,
});

ty::TyVid { index: index as u32 }
}

Expand Down Expand Up @@ -204,7 +221,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
}

sv::UndoLog::Other(SpecifyVar(vid, _, _)) => {
sv::UndoLog::Other(SpecifyVar(vid, _)) => {
if vid.index < new_elem_threshold {
// quick check to see if this variable was
// created since the snapshot started or not.
Expand All @@ -221,28 +238,34 @@ impl<'tcx> TypeVariableTable<'tcx> {
escaping_types
}

pub fn unsolved_variables(&self) -> Vec<ty::TyVid> {
pub fn candidates_for_defaulting(&self) -> Vec<(ty::TyVid, Default<'tcx>)> {
self.values
.iter()
.enumerate()
.filter_map(|(i, value)| match &value.value {
&TypeVariableValue::Known(_) => None,
&TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 })
})
.collect()
.filter_map(|(i, value)| {
let vid = match &value.value {
&TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 }),
&TypeVariableValue::Known(v) => match v.sty {
ty::TyInfer(ty::FloatVar(_)) | ty::TyInfer(ty::IntVar(_)) =>
Some(ty::TyVid { index: i as u32 }),
_ => None
}
};
vid.map(|v| (v, value.default.clone()))
})
.collect()
}
}

impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
type Value = TypeVariableData<'tcx>;
type Undo = UndoEntry<'tcx>;
type Undo = UndoEntry;

fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry<'tcx>) {
fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry) {
match action {
SpecifyVar(vid, relations, default) => {
SpecifyVar(vid, relations) => {
values[vid.index as usize].value = Bounded {
relations: relations,
default: default
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub enum TypeError<'tcx> {
ConvergenceMismatch(ExpectedFound<bool>),
ProjectionNameMismatched(ExpectedFound<Name>),
ProjectionBoundsLength(ExpectedFound<usize>),
TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>)
TyParamDefaultMismatch(ExpectedFound<type_variable::UserDefault<'tcx>>)
}

#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
Expand Down
Loading