break type-checking of aggregate-kind out into helper function
This commit is contained in:
parent
31d61f1f86
commit
45f6027196
1 changed files with 52 additions and 45 deletions
|
@ -1031,13 +1031,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn aggregate_field_ty(
|
fn aggregate_field_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
ak: &Box<AggregateKind<'tcx>>,
|
ak: &AggregateKind<'tcx>,
|
||||||
field_index: usize,
|
field_index: usize,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> Result<Ty<'tcx>, FieldAccessError> {
|
) -> Result<Ty<'tcx>, FieldAccessError> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
match **ak {
|
match *ak {
|
||||||
AggregateKind::Adt(def, variant_index, substs, active_field_index) => {
|
AggregateKind::Adt(def, variant_index, substs, active_field_index) => {
|
||||||
let variant = &def.variants[variant_index];
|
let variant = &def.variants[variant_index];
|
||||||
let adj_field_index = active_field_index.unwrap_or(field_index);
|
let adj_field_index = active_field_index.unwrap_or(field_index);
|
||||||
|
@ -1069,56 +1069,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AggregateKind::Array(ty) => {
|
AggregateKind::Array(ty) => Ok(ty),
|
||||||
Ok(ty)
|
|
||||||
}
|
|
||||||
AggregateKind::Tuple => {
|
AggregateKind::Tuple => {
|
||||||
unreachable!("This should have been covered in check_rvalues");
|
unreachable!("This should have been covered in check_rvalues");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_rvalue(&mut self, mir: &Mir<'tcx>, rv: &Rvalue<'tcx>, location: Location) {
|
fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||||
let tcx = self.tcx();
|
match rvalue {
|
||||||
match rv {
|
|
||||||
Rvalue::Aggregate(ak, ops) => {
|
Rvalue::Aggregate(ak, ops) => {
|
||||||
match **ak {
|
self.check_aggregate_rvalue(mir, rvalue, ak, ops, location)
|
||||||
// tuple rvalue field type is always the type of the op. Nothing to check here.
|
|
||||||
AggregateKind::Tuple => {}
|
|
||||||
_ => {
|
|
||||||
for (i, op) in ops.iter().enumerate() {
|
|
||||||
let field_ty = match self.aggregate_field_ty(ak, i, location) {
|
|
||||||
Ok(field_ty) => field_ty,
|
|
||||||
Err(FieldAccessError::OutOfRange { field_count }) => {
|
|
||||||
span_mirbug!(
|
|
||||||
self,
|
|
||||||
rv,
|
|
||||||
"accessed field #{} but variant only has {}",
|
|
||||||
i,
|
|
||||||
field_count
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let op_ty = op.ty(mir, tcx);
|
|
||||||
if let Err(terr) = self.sub_types(
|
|
||||||
op_ty,
|
|
||||||
field_ty,
|
|
||||||
location.at_successor_within_block(),
|
|
||||||
)
|
|
||||||
{
|
|
||||||
span_mirbug!(
|
|
||||||
self,
|
|
||||||
rv,
|
|
||||||
"{:?} is not a subtype of {:?}: {:?}",
|
|
||||||
op_ty,
|
|
||||||
field_ty,
|
|
||||||
terr
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// FIXME: These other cases have to be implemented in future PRs
|
// FIXME: These other cases have to be implemented in future PRs
|
||||||
Rvalue::Use(..) |
|
Rvalue::Use(..) |
|
||||||
|
@ -1134,6 +1095,52 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_aggregate_rvalue(
|
||||||
|
&mut self,
|
||||||
|
mir: &Mir<'tcx>,
|
||||||
|
rvalue: &Rvalue<'tcx>,
|
||||||
|
aggregate_kind: &AggregateKind<'tcx>,
|
||||||
|
operands: &[Operand<'tcx>],
|
||||||
|
location: Location,
|
||||||
|
) {
|
||||||
|
match aggregate_kind {
|
||||||
|
// tuple rvalue field type is always the type of the op. Nothing to check here.
|
||||||
|
AggregateKind::Tuple => return,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
for (i, operand) in operands.iter().enumerate() {
|
||||||
|
let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
|
||||||
|
Ok(field_ty) => field_ty,
|
||||||
|
Err(FieldAccessError::OutOfRange { field_count }) => {
|
||||||
|
span_mirbug!(
|
||||||
|
self,
|
||||||
|
rvalue,
|
||||||
|
"accessed field #{} but variant only has {}",
|
||||||
|
i,
|
||||||
|
field_count
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let operand_ty = operand.ty(mir, tcx);
|
||||||
|
if let Err(terr) =
|
||||||
|
self.sub_types(operand_ty, field_ty, location.at_successor_within_block())
|
||||||
|
{
|
||||||
|
span_mirbug!(
|
||||||
|
self,
|
||||||
|
rvalue,
|
||||||
|
"{:?} is not a subtype of {:?}: {:?}",
|
||||||
|
operand_ty,
|
||||||
|
field_ty,
|
||||||
|
terr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
|
fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
|
||||||
self.last_span = mir.span;
|
self.last_span = mir.span;
|
||||||
debug!("run_on_mir: {:?}", mir.span);
|
debug!("run_on_mir: {:?}", mir.span);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue